From 28a64358010a95d6adc6c91de5ae98ac149c3438 Mon Sep 17 00:00:00 2001 From: MATILLAT Quentin Date: Sat, 14 Dec 2024 16:26:01 +0100 Subject: [PATCH] feat(json): Add feature to expose JSON as raw scalar Signed-off-by: MATILLAT Quentin --- Cargo.toml | 1 + src/builder.rs | 9 +++++++++ src/builder_context/types_map.rs | 21 +++++++++++++-------- src/outputs/entity_object.rs | 8 +++++++- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c9431bf..f10ee8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ fnv = { version = "1.0.7" } [features] default = ["field-camel-case"] with-json = ["sea-orm/with-json"] +with-json-as-scalar = ["with-json"] with-chrono = ["sea-orm/with-chrono", "async-graphql/chrono"] with-time = ["sea-orm/with-time", "async-graphql/time"] with-uuid = ["sea-orm/with-uuid"] diff --git a/src/builder.rs b/src/builder.rs index 031c5f1..d00fffa 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -264,6 +264,15 @@ impl Builder { .into_iter() .fold(schema, |schema, cur| schema.register(cur)); + #[cfg(feature = "with-json-as-scalar")] + let schema = schema.register( + async_graphql::dynamic::Scalar::new(&self.context.types.json_name) + .description("The `JSON` scalar type represents raw JSON values") + .specified_by_url( + "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf", + ), + ); + schema .register( OrderByEnumBuilder { diff --git a/src/builder_context/types_map.rs b/src/builder_context/types_map.rs index f2f0019..e20a497 100644 --- a/src/builder_context/types_map.rs +++ b/src/builder_context/types_map.rs @@ -23,6 +23,10 @@ pub struct TypesMapConfig { pub time_library: TimeLibrary, /// used to configure default decimal library pub decimal_library: DecimalLibrary, + + #[cfg(feature = "with-json-as-scalar")] + /// used to expose Json as a Scalar + pub json_name: String, } impl std::default::Default for TypesMapConfig { @@ -45,6 +49,9 @@ impl std::default::Default for TypesMapConfig { decimal_library: DecimalLibrary::Decimal, #[cfg(all(not(feature = "with-decimal"), feature = "with-bigdecimal"))] decimal_library: DecimalLibrary::BigDecimal, + + #[cfg(feature = "with-json-as-scalar")] + json_name: "Json".to_owned(), } } } @@ -159,14 +166,9 @@ impl TypesMapHelper { ColumnType::Boolean => ConvertedType::Bool, #[cfg(not(feature = "with-json"))] - ColumnType::Json => ConvertedType::String, + ColumnType::Json | ColumnType::JsonBinary => ConvertedType::String, #[cfg(feature = "with-json")] - ColumnType::Json => ConvertedType::Json, - - // FIXME: how should we map them JsonBinary type ? - // #[cfg(feature = "with-json")] - // ColumnType::JsonBinary => ConvertedType::Json, - ColumnType::JsonBinary => ConvertedType::String, + ColumnType::Json | ColumnType::JsonBinary => ConvertedType::Json, #[cfg(not(feature = "with-uuid"))] ColumnType::Uuid => ConvertedType::String, @@ -280,7 +282,10 @@ impl TypesMapHelper { | ColumnType::Blob => Some(TypeRef::named(TypeRef::STRING)), ColumnType::Boolean => Some(TypeRef::named(TypeRef::BOOLEAN)), // FIXME: support json type + #[cfg(not(feature = "with-json-as-scalar"))] ColumnType::Json | ColumnType::JsonBinary => None, + #[cfg(feature = "with-json-as-scalar")] + ColumnType::Json | ColumnType::JsonBinary => Some(TypeRef::named(&self.context.types.json_name)), ColumnType::Uuid => Some(TypeRef::named(TypeRef::STRING)), ColumnType::Enum { name: enum_name, @@ -850,4 +855,4 @@ pub fn decode_hex(s: &str) -> Result, ParseIntError> { .step_by(2) .map(|i| u8::from_str_radix(&s[i..i + 2], 16)) .collect() -} +} \ No newline at end of file diff --git a/src/outputs/entity_object.rs b/src/outputs/entity_object.rs index 18db75f..c005bc9 100644 --- a/src/outputs/entity_object.rs +++ b/src/outputs/entity_object.rs @@ -236,7 +236,13 @@ fn sea_query_value_to_graphql_value( #[cfg(feature = "with-json")] #[cfg_attr(docsrs, doc(cfg(feature = "with-json")))] - sea_orm::sea_query::Value::Json(value) => value.map(|it| Value::from(it.to_string())), + sea_orm::sea_query::Value::Json(value) => value.map(|it| { + if cfg!(feature = "with-json-as-scalar") { + Value::from_json((*it).clone()).expect("Unable to serialize") + } else { + Value::from(it.to_string()) + } + }), #[cfg(feature = "with-chrono")] #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]