Skip to main content

juniper/integrations/
serde.rs

1use std::{fmt, marker::PhantomData};
2
3use indexmap::IndexMap;
4use serde::{
5    Deserialize, Serialize,
6    de::{self, Deserializer, IntoDeserializer as _},
7    ser::{SerializeMap as _, Serializer},
8    serde_if_integer128,
9};
10
11use crate::{
12    DefaultScalarValue, GraphQLError, Object, Value,
13    ast::InputValue,
14    executor::ExecutionError,
15    parser::{ParseError, SourcePosition, Spanning},
16    validation::RuleError,
17};
18
19impl<T: Serialize> Serialize for ExecutionError<T> {
20    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
21        let mut map = ser.serialize_map(Some(4))?;
22
23        map.serialize_key("message")?;
24        map.serialize_value(self.error().message())?;
25
26        let locations = vec![self.location()];
27        map.serialize_key("locations")?;
28        map.serialize_value(&locations)?;
29
30        map.serialize_key("path")?;
31        map.serialize_value(self.path())?;
32
33        if !self.error().extensions().is_null() {
34            map.serialize_key("extensions")?;
35            map.serialize_value(self.error().extensions())?;
36        }
37
38        map.end()
39    }
40}
41
42impl Serialize for GraphQLError {
43    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
44        #[derive(Serialize)]
45        struct Helper {
46            message: &'static str,
47        }
48
49        match self {
50            Self::ParseError(e) => [e].serialize(ser),
51            Self::ValidationError(es) => es.serialize(ser),
52            Self::NoOperationProvided => [Helper {
53                message: "Must provide an operation",
54            }]
55            .serialize(ser),
56            Self::MultipleOperationsProvided => [Helper {
57                message: "Must provide operation name \
58                          if query contains multiple operations",
59            }]
60            .serialize(ser),
61            Self::UnknownOperationName => [Helper {
62                message: "Unknown operation",
63            }]
64            .serialize(ser),
65            Self::IsSubscription => [Helper {
66                message: "Expected query, got subscription",
67            }]
68            .serialize(ser),
69            Self::NotSubscription => [Helper {
70                message: "Expected subscription, got query",
71            }]
72            .serialize(ser),
73        }
74    }
75}
76
77impl<'de, S: Deserialize<'de>> Deserialize<'de> for InputValue<S> {
78    fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
79        struct Visitor<S: ?Sized>(PhantomData<S>);
80
81        impl<'de, S: Deserialize<'de>> de::Visitor<'de> for Visitor<S> {
82            type Value = InputValue<S>;
83
84            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85                f.write_str("a valid input value")
86            }
87
88            fn visit_bool<E: de::Error>(self, b: bool) -> Result<Self::Value, E> {
89                S::deserialize(b.into_deserializer()).map(InputValue::Scalar)
90            }
91
92            fn visit_i8<E: de::Error>(self, n: i8) -> Result<Self::Value, E> {
93                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
94            }
95
96            fn visit_i16<E: de::Error>(self, n: i16) -> Result<Self::Value, E> {
97                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
98            }
99
100            fn visit_i32<E: de::Error>(self, n: i32) -> Result<Self::Value, E> {
101                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
102            }
103
104            fn visit_i64<E: de::Error>(self, n: i64) -> Result<Self::Value, E> {
105                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
106            }
107
108            serde_if_integer128! {
109                fn visit_i128<E: de::Error>(self, n: i128) ->  Result<Self::Value, E> {
110                    S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
111                }
112            }
113
114            fn visit_u8<E: de::Error>(self, n: u8) -> Result<Self::Value, E> {
115                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
116            }
117
118            fn visit_u16<E: de::Error>(self, n: u16) -> Result<Self::Value, E> {
119                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
120            }
121
122            fn visit_u32<E: de::Error>(self, n: u32) -> Result<Self::Value, E> {
123                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
124            }
125
126            fn visit_u64<E: de::Error>(self, n: u64) -> Result<Self::Value, E> {
127                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
128            }
129
130            serde_if_integer128! {
131                fn visit_u128<E: de::Error>(self, n: u128) ->  Result<Self::Value, E> {
132                    S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
133                }
134            }
135
136            fn visit_f32<E: de::Error>(self, n: f32) -> Result<Self::Value, E> {
137                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
138            }
139
140            fn visit_f64<E: de::Error>(self, n: f64) -> Result<Self::Value, E> {
141                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
142            }
143
144            fn visit_char<E: de::Error>(self, c: char) -> Result<Self::Value, E> {
145                S::deserialize(c.into_deserializer()).map(InputValue::Scalar)
146            }
147
148            fn visit_str<E: de::Error>(self, s: &str) -> Result<Self::Value, E> {
149                S::deserialize(s.into_deserializer()).map(InputValue::Scalar)
150            }
151
152            fn visit_string<E: de::Error>(self, s: String) -> Result<Self::Value, E> {
153                S::deserialize(s.into_deserializer()).map(InputValue::Scalar)
154            }
155
156            fn visit_bytes<E: de::Error>(self, b: &[u8]) -> Result<Self::Value, E> {
157                S::deserialize(b.into_deserializer()).map(InputValue::Scalar)
158            }
159
160            fn visit_byte_buf<E: de::Error>(self, b: Vec<u8>) -> Result<Self::Value, E> {
161                S::deserialize(b.into_deserializer()).map(InputValue::Scalar)
162            }
163
164            fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
165                Ok(InputValue::Null)
166            }
167
168            fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
169                Ok(InputValue::Null)
170            }
171
172            fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
173            where
174                V: de::SeqAccess<'de>,
175            {
176                let mut vals = Vec::new();
177                while let Some(v) = visitor.next_element()? {
178                    vals.push(v);
179                }
180                Ok(InputValue::list(vals))
181            }
182
183            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
184            where
185                V: de::MapAccess<'de>,
186            {
187                let mut obj = IndexMap::<String, InputValue<S>>::with_capacity(
188                    visitor.size_hint().unwrap_or(0),
189                );
190                while let Some((key, val)) = visitor.next_entry()? {
191                    obj.insert(key, val);
192                }
193                Ok(InputValue::object(obj))
194            }
195        }
196
197        de.deserialize_any(Visitor(PhantomData))
198    }
199}
200
201impl<T: Serialize> Serialize for InputValue<T> {
202    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
203        match self {
204            Self::Null | Self::Variable(_) => ser.serialize_unit(),
205            Self::Scalar(s) => s.serialize(ser),
206            Self::Enum(e) => ser.serialize_str(e),
207            Self::List(l) => l.iter().map(|x| &x.item).collect::<Vec<_>>().serialize(ser),
208            Self::Object(o) => o
209                .iter()
210                .map(|(k, v)| (k.item.as_str(), &v.item))
211                .collect::<IndexMap<_, _>>()
212                .serialize(ser),
213        }
214    }
215}
216
217impl Serialize for RuleError {
218    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
219        let mut map = ser.serialize_map(Some(2))?;
220
221        map.serialize_key("message")?;
222        map.serialize_value(self.message())?;
223
224        map.serialize_key("locations")?;
225        map.serialize_value(self.locations())?;
226
227        map.end()
228    }
229}
230
231impl Serialize for SourcePosition {
232    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
233        let mut map = ser.serialize_map(Some(2))?;
234
235        let line = self.line() + 1;
236        map.serialize_key("line")?;
237        map.serialize_value(&line)?;
238
239        let column = self.column() + 1;
240        map.serialize_key("column")?;
241        map.serialize_value(&column)?;
242
243        map.end()
244    }
245}
246
247impl Serialize for Spanning<ParseError> {
248    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
249        let mut map = ser.serialize_map(Some(2))?;
250
251        let msg = self.item.to_string();
252        map.serialize_key("message")?;
253        map.serialize_value(&msg)?;
254
255        let mut loc = IndexMap::new();
256        loc.insert("line".to_owned(), self.start().line() + 1);
257        loc.insert("column".to_owned(), self.start().column() + 1);
258
259        let locations = vec![loc];
260        map.serialize_key("locations")?;
261        map.serialize_value(&locations)?;
262
263        map.end()
264    }
265}
266
267impl<T: Serialize> Serialize for Object<T> {
268    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
269        let mut map = ser.serialize_map(Some(self.field_count()))?;
270        for (f, v) in self.iter() {
271            map.serialize_key(f)?;
272            map.serialize_value(v)?;
273        }
274        map.end()
275    }
276}
277
278impl<T: Serialize> Serialize for Value<T> {
279    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
280        match self {
281            Self::Null => ser.serialize_unit(),
282            Self::Scalar(s) => s.serialize(ser),
283            Self::List(l) => l.serialize(ser),
284            Self::Object(o) => o.serialize(ser),
285        }
286    }
287}
288
289impl<'de> Deserialize<'de> for DefaultScalarValue {
290    fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
291        struct Visitor;
292
293        impl de::Visitor<'_> for Visitor {
294            type Value = DefaultScalarValue;
295
296            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
297                f.write_str("a valid input value")
298            }
299
300            fn visit_bool<E: de::Error>(self, b: bool) -> Result<Self::Value, E> {
301                Ok(DefaultScalarValue::Boolean(b))
302            }
303
304            fn visit_i64<E: de::Error>(self, n: i64) -> Result<Self::Value, E> {
305                if n >= i64::from(i32::MIN) && n <= i64::from(i32::MAX) {
306                    Ok(DefaultScalarValue::Int(n.try_into().unwrap()))
307                } else {
308                    // Browser's `JSON.stringify()` serializes all numbers
309                    // having no fractional part as integers (no decimal point),
310                    // so we must parse large integers as floating point,
311                    // otherwise we would error on transferring large floating
312                    // point numbers.
313                    // TODO: Use `FloatToInt` conversion once stabilized:
314                    //       https://github.com/rust-lang/rust/issues/67057
315                    Ok(DefaultScalarValue::Float(n as f64))
316                }
317            }
318
319            fn visit_u64<E: de::Error>(self, n: u64) -> Result<Self::Value, E> {
320                if n <= u64::try_from(i32::MAX).unwrap() {
321                    self.visit_i64(n.try_into().unwrap())
322                } else {
323                    // Browser's `JSON.stringify()` serializes all numbers
324                    // having no fractional part as integers (no decimal point),
325                    // so we must parse large integers as floating point,
326                    // otherwise we would error on transferring large floating
327                    // point numbers.
328                    // TODO: Use `FloatToInt` conversion once stabilized:
329                    //       https://github.com/rust-lang/rust/issues/67057
330                    Ok(DefaultScalarValue::Float(n as f64))
331                }
332            }
333
334            fn visit_f64<E: de::Error>(self, f: f64) -> Result<Self::Value, E> {
335                Ok(DefaultScalarValue::Float(f))
336            }
337
338            fn visit_str<E: de::Error>(self, s: &str) -> Result<Self::Value, E> {
339                self.visit_string(s.into())
340            }
341
342            fn visit_string<E: de::Error>(self, s: String) -> Result<Self::Value, E> {
343                Ok(DefaultScalarValue::String(s))
344            }
345        }
346
347        de.deserialize_any(Visitor)
348    }
349}
350
351#[cfg(test)]
352mod tests {
353    use serde_json::{from_str, to_string};
354
355    use crate::{DefaultScalarValue, FieldError, InputValue, graphql_input_value, graphql_value};
356
357    use super::{ExecutionError, GraphQLError};
358
359    #[test]
360    fn int() {
361        assert_eq!(
362            from_str::<InputValue>("1235").unwrap(),
363            graphql_input_value!(1235),
364        );
365    }
366
367    #[test]
368    fn float() {
369        assert_eq!(
370            from_str::<InputValue>("2.0").unwrap(),
371            graphql_input_value!(2.0),
372        );
373        // large value without a decimal part is also float
374        assert_eq!(
375            from_str::<InputValue>("123567890123").unwrap(),
376            graphql_input_value!(123_567_890_123.0),
377        );
378    }
379
380    #[test]
381    fn errors() {
382        assert_eq!(
383            to_string(&GraphQLError::UnknownOperationName).unwrap(),
384            r#"[{"message":"Unknown operation"}]"#,
385        );
386    }
387
388    #[test]
389    fn error_extensions() {
390        assert_eq!(
391            to_string(&ExecutionError::at_origin(
392                FieldError::<DefaultScalarValue>::new("foo error", graphql_value!({"foo": "bar"})),
393            ))
394            .unwrap(),
395            r#"{"message":"foo error","locations":[{"line":1,"column":1}],"path":[],"extensions":{"foo":"bar"}}"#,
396        );
397    }
398}