mongo_graphql/helpers/
serialization.rs1use crate::error::GraphQLError;
2use crate::schema::definition::{CollectionDef, FieldType, RelationKind};
3use async_graphql::dynamic::FieldValue;
4use mongodb::bson::Bson;
5
6pub fn document_to_graphql_value(
8 doc: &mongodb::bson::Document,
9 collection_def: &CollectionDef,
10) -> serde_json::Value {
11 let mut map = serde_json::Map::new();
12
13 for field_def in &collection_def.fields {
14 if let FieldType::Relation(rel) = &field_def.field_type {
15 match rel.kind {
16 RelationKind::OneToMany | RelationKind::OneToOne => {
17 if let Some(bson) = doc.get(&field_def.name) {
18 map.insert(field_def.name.clone(), bson_to_json(bson));
19 }
20 }
21 RelationKind::ManyToMany => {}
22 }
23 continue;
24 }
25
26 let gql_name = field_def.graphql_name();
27 match doc.get(&field_def.name) {
28 Some(bson) => {
29 map.insert(gql_name, bson_to_json(bson));
30 }
31 None => {}
35 }
36 }
37
38 serde_json::Value::Object(map)
39}
40
41pub fn bson_to_json(bson: &Bson) -> serde_json::Value {
43 match bson {
44 Bson::ObjectId(oid) => serde_json::Value::String(oid.to_hex()),
45 Bson::String(s) => serde_json::Value::String(s.clone()),
46 Bson::Int32(i) => serde_json::Value::Number((*i).into()),
47 Bson::Int64(i) => serde_json::Value::Number((*i).into()),
48 Bson::Double(f) => serde_json::Number::from_f64(*f)
49 .map(serde_json::Value::Number)
50 .unwrap_or(serde_json::Value::Null),
51 Bson::Boolean(b) => serde_json::Value::Bool(*b),
52 Bson::DateTime(dt) => {
53 let millis = dt.timestamp_millis();
54 let secs = millis / 1000;
55 let nanos = ((millis % 1000) * 1_000_000) as u32;
56 match chrono::DateTime::from_timestamp(secs, nanos) {
57 Some(chrono_dt) => serde_json::Value::String(chrono_dt.to_rfc3339()),
58 None => serde_json::Value::Null,
59 }
60 }
61 Bson::Array(arr) => {
62 serde_json::Value::Array(arr.iter().map(bson_to_json).collect())
63 }
64 Bson::Document(subdoc) => {
65 serde_json::Value::Object(
66 subdoc.iter().map(|(key, value)| (key.clone(), bson_to_json(value))).collect(),
67 )
68 }
69 Bson::Null | Bson::Undefined => serde_json::Value::Null,
70 _ => serde_json::Value::Null,
71 }
72}
73
74pub fn input_doc_to_mongo(doc: mongodb::bson::Document, collection_def: &CollectionDef) -> mongodb::bson::Document {
79 let mut mapped = mongodb::bson::Document::new();
80 for (key, value) in doc {
81 let field_def = collection_def
82 .fields
83 .iter()
84 .find(|field| field.graphql_name() == key);
85 let mongo_name = field_def
86 .map(|field| field.name.clone())
87 .unwrap_or_else(|| key.clone());
88
89 let mapped_value = match field_def {
90 Some(f) if matches!(f.field_type, FieldType::Relation(_)) => {
91 continue;
95 }
96 _ => value,
97 };
98 mapped.insert(mongo_name, mapped_value);
99 }
100 mapped
101}
102
103pub fn json_to_field_value(json: serde_json::Value) -> Result<FieldValue<'static>, GraphQLError> {
105 async_graphql::Value::try_from(json)
106 .map(FieldValue::value)
107 .map_err(|e| GraphQLError::Internal(format!("Value conversion: {}", e)))
108}