@@ -207,13 +207,13 @@ fn convert_object_to_json(buffer: &mut impl Write, obj: &VariantObject) -> Resul
207207fn convert_array_to_json ( buffer : & mut impl Write , arr : & VariantList ) -> Result < ( ) , ArrowError > {
208208 write ! ( buffer, "[" ) ?;
209209
210- let len = arr . len ( ) ;
211- for i in 0 ..len {
212- if i > 0 {
210+ let mut first = true ;
211+ for element in arr . iter ( ) {
212+ if !first {
213213 write ! ( buffer, "," ) ?;
214214 }
215+ first = false ;
215216
216- let element = arr. get ( i) ?;
217217 variant_to_json ( buffer, & element) ?;
218218 }
219219
@@ -336,7 +336,7 @@ pub fn variant_to_json_value(variant: &Variant) -> Result<Value, ArrowError> {
336336 Variant :: Int16 ( i) => Ok ( Value :: Number ( ( * i) . into ( ) ) ) ,
337337 Variant :: Int32 ( i) => Ok ( Value :: Number ( ( * i) . into ( ) ) ) ,
338338 Variant :: Int64 ( i) => Ok ( Value :: Number ( ( * i) . into ( ) ) ) ,
339- Variant :: Float ( f) => serde_json:: Number :: from_f64 ( * f as f64 )
339+ Variant :: Float ( f) => serde_json:: Number :: from_f64 ( ( * f ) . into ( ) )
340340 . map ( Value :: Number )
341341 . ok_or_else ( || ArrowError :: InvalidArgumentError ( "Invalid float value" . to_string ( ) ) ) ,
342342 Variant :: Double ( f) => serde_json:: Number :: from_f64 ( * f)
@@ -350,12 +350,14 @@ pub fn variant_to_json_value(variant: &Variant) -> Result<Value, ArrowError> {
350350 let divisor = 10_i32 . pow ( * scale as u32 ) ;
351351 let quotient = integer / divisor;
352352 let remainder = ( integer % divisor) . abs ( ) ;
353- let formatted_remainder = format ! ( "{:0width$}" , remainder, width = * scale as usize ) ;
354- let trimmed_remainder = formatted_remainder. trim_end_matches ( '0' ) ;
355353
356- let decimal_str = if trimmed_remainder . is_empty ( ) {
354+ let decimal_str = if remainder == 0 {
357355 quotient. to_string ( )
358356 } else {
357+ // The {:0width$} format ensures it correctly renders with leading zeros (e.g., .0000100)
358+ let formatted_remainder = format ! ( "{:0width$}" , remainder, width = * scale as usize ) ;
359+ // Then strip away any trailing zeros (e.g., .00001)
360+ let trimmed_remainder = formatted_remainder. trim_end_matches ( '0' ) ;
359361 format ! ( "{}.{}" , quotient, trimmed_remainder)
360362 } ;
361363
@@ -376,12 +378,14 @@ pub fn variant_to_json_value(variant: &Variant) -> Result<Value, ArrowError> {
376378 let divisor = 10_i64 . pow ( * scale as u32 ) ;
377379 let quotient = integer / divisor;
378380 let remainder = ( integer % divisor) . abs ( ) ;
379- let formatted_remainder = format ! ( "{:0width$}" , remainder, width = * scale as usize ) ;
380- let trimmed_remainder = formatted_remainder. trim_end_matches ( '0' ) ;
381381
382- let decimal_str = if trimmed_remainder . is_empty ( ) {
382+ let decimal_str = if remainder == 0 {
383383 quotient. to_string ( )
384384 } else {
385+ // The {:0width$} format ensures it correctly renders with leading zeros (e.g., .0000100)
386+ let formatted_remainder = format ! ( "{:0width$}" , remainder, width = * scale as usize ) ;
387+ // Then strip away any trailing zeros (e.g., .00001)
388+ let trimmed_remainder = formatted_remainder. trim_end_matches ( '0' ) ;
385389 format ! ( "{}.{}" , quotient, trimmed_remainder)
386390 } ;
387391
@@ -402,12 +406,14 @@ pub fn variant_to_json_value(variant: &Variant) -> Result<Value, ArrowError> {
402406 let divisor = 10_i128 . pow ( * scale as u32 ) ;
403407 let quotient = integer / divisor;
404408 let remainder = ( integer % divisor) . abs ( ) ;
405- let formatted_remainder = format ! ( "{:0width$}" , remainder, width = * scale as usize ) ;
406- let trimmed_remainder = formatted_remainder. trim_end_matches ( '0' ) ;
407409
408- let decimal_str = if trimmed_remainder . is_empty ( ) {
410+ let decimal_str = if remainder == 0 {
409411 quotient. to_string ( )
410412 } else {
413+ // The {:0width$} format ensures it correctly renders with leading zeros (e.g., .0000100)
414+ let formatted_remainder = format ! ( "{:0width$}" , remainder, width = * scale as usize ) ;
415+ // Then strip away any trailing zeros (e.g., .00001)
416+ let trimmed_remainder = formatted_remainder. trim_end_matches ( '0' ) ;
411417 format ! ( "{}.{}" , quotient, trimmed_remainder)
412418 } ;
413419
@@ -1246,4 +1252,52 @@ mod tests {
12461252
12471253 Ok ( ( ) )
12481254 }
1255+
1256+ #[ test]
1257+ fn test_float_nan_inf_handling ( ) -> Result < ( ) , ArrowError > {
1258+ // Test NaN handling - should return an error since JSON doesn't support NaN
1259+ let nan_variant = Variant :: Float ( f32:: NAN ) ;
1260+ let nan_result = variant_to_json_value ( & nan_variant) ;
1261+ assert ! ( nan_result. is_err( ) ) ;
1262+ assert ! ( nan_result. unwrap_err( ) . to_string( ) . contains( "Invalid float value" ) ) ;
1263+
1264+ // Test positive infinity - should return an error since JSON doesn't support Infinity
1265+ let pos_inf_variant = Variant :: Float ( f32:: INFINITY ) ;
1266+ let pos_inf_result = variant_to_json_value ( & pos_inf_variant) ;
1267+ assert ! ( pos_inf_result. is_err( ) ) ;
1268+ assert ! ( pos_inf_result. unwrap_err( ) . to_string( ) . contains( "Invalid float value" ) ) ;
1269+
1270+ // Test negative infinity - should return an error since JSON doesn't support -Infinity
1271+ let neg_inf_variant = Variant :: Float ( f32:: NEG_INFINITY ) ;
1272+ let neg_inf_result = variant_to_json_value ( & neg_inf_variant) ;
1273+ assert ! ( neg_inf_result. is_err( ) ) ;
1274+ assert ! ( neg_inf_result. unwrap_err( ) . to_string( ) . contains( "Invalid float value" ) ) ;
1275+
1276+ // Test the same for Double variants
1277+ let nan_double_variant = Variant :: Double ( f64:: NAN ) ;
1278+ let nan_double_result = variant_to_json_value ( & nan_double_variant) ;
1279+ assert ! ( nan_double_result. is_err( ) ) ;
1280+ assert ! ( nan_double_result. unwrap_err( ) . to_string( ) . contains( "Invalid double value" ) ) ;
1281+
1282+ let pos_inf_double_variant = Variant :: Double ( f64:: INFINITY ) ;
1283+ let pos_inf_double_result = variant_to_json_value ( & pos_inf_double_variant) ;
1284+ assert ! ( pos_inf_double_result. is_err( ) ) ;
1285+ assert ! ( pos_inf_double_result. unwrap_err( ) . to_string( ) . contains( "Invalid double value" ) ) ;
1286+
1287+ let neg_inf_double_variant = Variant :: Double ( f64:: NEG_INFINITY ) ;
1288+ let neg_inf_double_result = variant_to_json_value ( & neg_inf_double_variant) ;
1289+ assert ! ( neg_inf_double_result. is_err( ) ) ;
1290+ assert ! ( neg_inf_double_result. unwrap_err( ) . to_string( ) . contains( "Invalid double value" ) ) ;
1291+
1292+ // Test normal float values still work
1293+ let normal_float = Variant :: Float ( 3.14f32 ) ;
1294+ let normal_result = variant_to_json_value ( & normal_float) ?;
1295+ assert ! ( matches!( normal_result, Value :: Number ( _) ) ) ;
1296+
1297+ let normal_double = Variant :: Double ( 2.71828f64 ) ;
1298+ let normal_double_result = variant_to_json_value ( & normal_double) ?;
1299+ assert ! ( matches!( normal_double_result, Value :: Number ( _) ) ) ;
1300+
1301+ Ok ( ( ) )
1302+ }
12491303}
0 commit comments