shape/
from_json.rs

1use serde_json::Value as JSON;
2use serde_json_bytes::Value as JSONBytes;
3
4use super::Shape;
5use super::ShapeCase;
6
7impl Shape {
8    /// Derive a [`Shape`] from a JSON value, which is almost a lossless
9    /// conversion except that floating point literals get the general
10    /// [`ShapeCase::Float`] shape, ignoring their particular values.
11    ///
12    /// Note that all locations will be empty, because [`serde_json`] doesn't track locations.
13    ///
14    /// # Panics
15    ///
16    /// If the JSON value can't be converted into a [`serde_json_bytes::Value`]
17    #[must_use]
18    pub fn from_json(json: &JSON) -> Self {
19        Shape::new(ShapeCase::from_json(json), [])
20    }
21
22    /// Derive a [`Shape`] from a JSON value using the [`serde_json_bytes`] crate.
23    ///
24    /// Note that all locations will be empty, because [`serde_json_bytes`] doesn't track locations.
25    pub fn from_json_bytes(json: &JSONBytes) -> Self {
26        Shape::new(ShapeCase::from_json_bytes(json), [])
27    }
28}
29
30impl ShapeCase {
31    /// Derive a [`ShapeCase`] from a [`serde_json::Value`].
32    ///
33    /// # Panics
34    ///
35    /// If the [`serde_json::Value`] can't be converted into a [`serde_json_bytes::Value`]
36    #[must_use]
37    pub fn from_json(json: &JSON) -> Self {
38        Self::from_json_bytes(
39            &json
40                .to_string()
41                .parse()
42                .expect("serde_json_bytes doesn't match serde_json"),
43        )
44    }
45
46    pub fn from_json_bytes(json: &JSONBytes) -> Self {
47        match json {
48            JSONBytes::Bool(b) => Self::Bool(Some(*b)),
49            JSONBytes::String(s) => Self::String(Some(s.as_str().to_string())),
50            JSONBytes::Number(n) => {
51                if let Some(i) = n.as_i64() {
52                    Self::Int(Some(i))
53                } else {
54                    Self::Float
55                }
56            }
57            JSONBytes::Null => Self::Null,
58            JSONBytes::Array(arr) => {
59                let mut prefix = Vec::with_capacity(arr.len());
60                for item in arr {
61                    prefix.push(Shape::from_json_bytes(item));
62                }
63                Self::Array {
64                    prefix,
65                    tail: Shape::none(),
66                }
67            }
68            JSONBytes::Object(obj) => {
69                let mut fields = Shape::empty_map();
70                for (key, value) in obj {
71                    fields.insert(key.as_str().to_string(), Shape::from_json_bytes(value));
72                }
73                Self::Object {
74                    fields,
75                    rest: Shape::none(),
76                }
77            }
78        }
79    }
80}