From 7c69a97fc48a9a22865e95cc2a1a23875601dd6e Mon Sep 17 00:00:00 2001 From: Haresh Khanna Date: Mon, 20 Jul 2026 11:11:45 +0100 Subject: [PATCH] fix(arrow-json): render coerced f32 as its value, not raw bits, in the string decoder --- arrow-json/src/reader/mod.rs | 15 +++++++++++++++ arrow-json/src/reader/string_array.rs | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arrow-json/src/reader/mod.rs b/arrow-json/src/reader/mod.rs index c14c1f9ea0f8..ea4cbe2664f6 100644 --- a/arrow-json/src/reader/mod.rs +++ b/arrow-json/src/reader/mod.rs @@ -2903,6 +2903,21 @@ mod tests { ); } + #[test] + fn test_serialize_f32_into_string() { + // Coercing an f32 into a string column must render the value, not its raw bit pattern. + let field = Field::new("f", DataType::Utf8, true); + let mut decoder = ReaderBuilder::new_with_field(field) + .with_coerce_primitive(true) + .build_decoder() + .unwrap(); + decoder.serialize(&[1.5_f32, -2.25_f32]).unwrap(); + let batch = decoder.flush().unwrap().unwrap(); + let values = batch.column(0).as_string::(); + assert_eq!(values.value(0), "1.5"); + assert_eq!(values.value(1), "-2.25"); + } + // Parse the given `row` in `struct_mode` as a type given by fields. // // If as_struct == true, wrap the fields in a Struct field with name "r". diff --git a/arrow-json/src/reader/string_array.rs b/arrow-json/src/reader/string_array.rs index 6b6abc21ede8..42ace8ef7da4 100644 --- a/arrow-json/src/reader/string_array.rs +++ b/arrow-json/src/reader/string_array.rs @@ -120,7 +120,7 @@ impl ArrayDecoder for StringArrayDecoder { builder.append_value(int_formatter.format(n)); } TapeElement::F32(n) if coerce_primitive => { - builder.append_value(int_formatter.format(n)); + builder.append_value(float_formatter.format_finite(f32::from_bits(n))); } TapeElement::F64(high) if coerce_primitive => match tape.get(p + 1) { TapeElement::F32(low) => {