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}