diff --git a/arrow/src/datatypes/mod.rs b/arrow/src/datatypes/mod.rs index 1f98a4afa91..aed16bd8bc1 100644 --- a/arrow/src/datatypes/mod.rs +++ b/arrow/src/datatypes/mod.rs @@ -56,6 +56,7 @@ mod tests { collections::{BTreeMap, HashMap}, f32::NAN, }; + use crate::json::JsonSerializable; #[test] fn test_list_datatype_equality() { diff --git a/arrow/src/datatypes/native.rs b/arrow/src/datatypes/native.rs index d9a3f667d8e..207e8cb4033 100644 --- a/arrow/src/datatypes/native.rs +++ b/arrow/src/datatypes/native.rs @@ -17,17 +17,11 @@ use super::DataType; use half::f16; -use serde_json::{Number, Value}; mod private { pub trait Sealed {} } -/// Trait declaring any type that is serializable to JSON. This includes all primitive types (bool, i32, etc.). -pub trait JsonSerializable: 'static { - fn into_json_value(self) -> Option; -} - /// Trait expressing a Rust type that has the same in-memory representation /// as Arrow. This includes `i16`, `f32`, but excludes `bool` (which in arrow is represented in bits). /// @@ -58,8 +52,8 @@ pub trait ArrowNativeType: + PartialOrd + std::str::FromStr + Default - + JsonSerializable + private::Sealed + + 'static { /// Convert native type from usize. #[inline] @@ -120,18 +114,6 @@ pub trait ArrowPrimitiveType: 'static { } } -impl JsonSerializable for bool { - fn into_json_value(self) -> Option { - Some(self.into()) - } -} - -impl JsonSerializable for i8 { - fn into_json_value(self) -> Option { - Some(self.into()) - } -} - impl private::Sealed for i8 {} impl ArrowNativeType for i8 { #[inline] @@ -150,12 +132,6 @@ impl ArrowNativeType for i8 { } } -impl JsonSerializable for i16 { - fn into_json_value(self) -> Option { - Some(self.into()) - } -} - impl private::Sealed for i16 {} impl ArrowNativeType for i16 { #[inline] @@ -174,12 +150,6 @@ impl ArrowNativeType for i16 { } } -impl JsonSerializable for i32 { - fn into_json_value(self) -> Option { - Some(self.into()) - } -} - impl private::Sealed for i32 {} impl ArrowNativeType for i32 { #[inline] @@ -204,12 +174,6 @@ impl ArrowNativeType for i32 { } } -impl JsonSerializable for i64 { - fn into_json_value(self) -> Option { - Some(Value::Number(Number::from(self))) - } -} - impl private::Sealed for i64 {} impl ArrowNativeType for i64 { #[inline] @@ -234,16 +198,6 @@ impl ArrowNativeType for i64 { } } -impl JsonSerializable for i128 { - fn into_json_value(self) -> Option { - // Serialize as string to avoid issues with arbitrary_precision serde_json feature - // - https://github.com/serde-rs/json/issues/559 - // - https://github.com/serde-rs/json/issues/845 - // - https://github.com/serde-rs/json/issues/846 - Some(self.to_string().into()) - } -} - impl private::Sealed for i128 {} impl ArrowNativeType for i128 { #[inline] @@ -268,12 +222,6 @@ impl ArrowNativeType for i128 { } } -impl JsonSerializable for u8 { - fn into_json_value(self) -> Option { - Some(self.into()) - } -} - impl private::Sealed for u8 {} impl ArrowNativeType for u8 { #[inline] @@ -292,12 +240,6 @@ impl ArrowNativeType for u8 { } } -impl JsonSerializable for u16 { - fn into_json_value(self) -> Option { - Some(self.into()) - } -} - impl private::Sealed for u16 {} impl ArrowNativeType for u16 { #[inline] @@ -316,12 +258,6 @@ impl ArrowNativeType for u16 { } } -impl JsonSerializable for u32 { - fn into_json_value(self) -> Option { - Some(self.into()) - } -} - impl private::Sealed for u32 {} impl ArrowNativeType for u32 { #[inline] @@ -340,12 +276,6 @@ impl ArrowNativeType for u32 { } } -impl JsonSerializable for u64 { - fn into_json_value(self) -> Option { - Some(self.into()) - } -} - impl private::Sealed for u64 {} impl ArrowNativeType for u64 { #[inline] @@ -364,24 +294,6 @@ impl ArrowNativeType for u64 { } } -impl JsonSerializable for f16 { - fn into_json_value(self) -> Option { - Number::from_f64(f64::round(f64::from(self) * 1000.0) / 1000.0).map(Value::Number) - } -} - -impl JsonSerializable for f32 { - fn into_json_value(self) -> Option { - Number::from_f64(f64::round(self as f64 * 1000.0) / 1000.0).map(Value::Number) - } -} - -impl JsonSerializable for f64 { - fn into_json_value(self) -> Option { - Number::from_f64(self).map(Value::Number) - } -} - impl ArrowNativeType for f16 {} impl private::Sealed for f16 {} impl ArrowNativeType for f32 {} diff --git a/arrow/src/json/mod.rs b/arrow/src/json/mod.rs index 6b3df188a47..836145bb08e 100644 --- a/arrow/src/json/mod.rs +++ b/arrow/src/json/mod.rs @@ -25,3 +25,58 @@ pub mod writer; pub use self::reader::Reader; pub use self::reader::ReaderBuilder; pub use self::writer::{ArrayWriter, LineDelimitedWriter, Writer}; +use half::f16; +use serde_json::{Number, Value}; + +/// Trait declaring any type that is serializable to JSON. This includes all primitive types (bool, i32, etc.). +pub trait JsonSerializable: 'static { + fn into_json_value(self) -> Option; +} + +macro_rules! json_serializable { + ($t:ty) => { + impl JsonSerializable for $t { + fn into_json_value(self) -> Option { + Some(self.into()) + } + } + }; +} + +json_serializable!(bool); +json_serializable!(u8); +json_serializable!(u16); +json_serializable!(u32); +json_serializable!(u64); +json_serializable!(i8); +json_serializable!(i16); +json_serializable!(i32); +json_serializable!(i64); + +impl JsonSerializable for i128 { + fn into_json_value(self) -> Option { + // Serialize as string to avoid issues with arbitrary_precision serde_json feature + // - https://github.com/serde-rs/json/issues/559 + // - https://github.com/serde-rs/json/issues/845 + // - https://github.com/serde-rs/json/issues/846 + Some(self.to_string().into()) + } +} + +impl JsonSerializable for f16 { + fn into_json_value(self) -> Option { + Number::from_f64(f64::round(f64::from(self) * 1000.0) / 1000.0).map(Value::Number) + } +} + +impl JsonSerializable for f32 { + fn into_json_value(self) -> Option { + Number::from_f64(f64::round(self as f64 * 1000.0) / 1000.0).map(Value::Number) + } +} + +impl JsonSerializable for f64 { + fn into_json_value(self) -> Option { + Number::from_f64(self).map(Value::Number) + } +} diff --git a/arrow/src/json/writer.rs b/arrow/src/json/writer.rs index f21dad04313..bf40b31b494 100644 --- a/arrow/src/json/writer.rs +++ b/arrow/src/json/writer.rs @@ -111,11 +111,14 @@ use serde_json::Value; use crate::array::*; use crate::datatypes::*; use crate::error::{ArrowError, Result}; +use crate::json::JsonSerializable; use crate::record_batch::RecordBatch; -fn primitive_array_to_json( - array: &ArrayRef, -) -> Result> { +fn primitive_array_to_json(array: &ArrayRef) -> Result> +where + T: ArrowPrimitiveType, + T::Native: JsonSerializable, +{ Ok(as_primitive_array::(array) .iter() .map(|maybe_value| match maybe_value { @@ -239,12 +242,15 @@ macro_rules! set_temporal_column_by_array_type { }; } -fn set_column_by_primitive_type( +fn set_column_by_primitive_type( rows: &mut [JsonMap], row_count: usize, array: &ArrayRef, col_name: &str, -) { +) where + T: ArrowPrimitiveType, + T::Native: JsonSerializable, +{ let primitive_arr = as_primitive_array::(array); rows.iter_mut()