jss_core/from/from_json/
parse_main.rs

1use super::*;
2use crate::{JssKind, JssSchema, JssValue};
3use json_value::{JsonMaybeObject, JsonValueCheck, JsonValueWrap};
4
5impl From<JsonValue> for JssValue {
6    fn from(v: JsonValue) -> Self {
7        match v {
8            JsonValue::Null => Self::Null,
9            JsonValue::Bool(v) => Self::Boolean(v),
10            JsonValue::Number(v) => Self::Number(v),
11            JsonValue::String(v) => Self::String(v),
12            JsonValue::Array(v) => Self::Array(v.into_iter().map(|v| v.into()).collect()),
13            JsonValue::Object(v) => Self::Object(v.into_iter().map(|(k, v)| (k, v.into())).collect()),
14        }
15    }
16}
17
18impl JssSchema {
19    pub fn parse_json_schema(top: JsonValue) -> Result<Self, Vec<JssError>> {
20        let mut errors = vec![];
21        match Self::try_parse_json_schema(top, &mut errors) {
22            Ok(o) => Ok(o),
23            Err(e) => {
24                errors.push(e);
25                Err(errors)
26            }
27        }
28    }
29
30    pub(crate) fn try_parse_json_schema(top: JsonValue, errors: Errors) -> Result<Self> {
31        let mut top = top;
32        // https://json-schema.org/understanding-json-schema/basics.html#id1
33        // Accepts anything, as long as it’s valid JSON
34        if top.is_true() || top.is_empty() {
35            return Ok(JssSchema::anything());
36        }
37        // https://json-schema.org/understanding-json-schema/basics.html#id1
38        // Schema that matches nothing.
39        if top.is_false() {
40            return Ok(JssSchema::nothing());
41        }
42        if top.is_null() || top.is_array() {
43            return Err(JssError::undefined_variable("TODO"));
44        }
45
46        let mut jss = JssSchema::top();
47
48        jss.parse_steps(true, &mut top, errors);
49        jss.consume_rest(top, errors);
50
51        Ok(jss)
52    }
53}
54
55impl JssSchema {
56    fn parse_value(name: String, value: JsonValue, errors: Errors) -> Result<Self> {
57        let mut value = value;
58        let mut jss = Self::default();
59        jss.set_name(name);
60        jss.parse_steps(false, &mut value, errors);
61        jss.consume_rest(value, errors);
62        Ok(jss)
63    }
64    fn parse_steps(&mut self, is_top: bool, value: &mut JsonValue, errors: Errors) {
65        self.parse_type(value, errors);
66        self.parse_name(value, errors);
67        self.parse_description(value, errors);
68        self.extend_properties("properties", is_top, value, errors);
69        self.extend_definition("$defs", value, errors);
70        self.extend_definition("definitions", value, errors);
71    }
72    fn consume_rest(&mut self, value: JsonValue, _: Errors) {
73        let object = match value.into_object() {
74            None => return,
75            Some(s) => s,
76        };
77        for (k, v) in object {
78            self.insert_attribute(k, v);
79        }
80    }
81}
82
83impl JssSchema {
84    fn extend_properties(&mut self, key: &str, is_top: bool, value: &mut JsonValue, errors: Errors) {
85        if let Some(object) = value.extract_key_as_object(key) {
86            for (key, value) in object {
87                match JssSchema::parse_value(key.to_owned(), value, errors) {
88                    Ok(mut o) => {
89                        if is_top {
90                            o.kind = JssKind::PropertyTop
91                        }
92                        self.insert_property(key, o);
93                    }
94                    Err(e) => errors.push(e),
95                }
96            }
97        }
98    }
99
100    fn extend_definition(&mut self, key: &str, value: &mut JsonValue, errors: Errors) {
101        if let Some(object) = value.extract_key_as_object(key) {
102            for (key, value) in object {
103                match JssSchema::parse_value(key.to_owned(), value, errors) {
104                    Ok(mut o) => {
105                        o.kind = JssKind::Definition;
106                        self.insert_definition(key, o);
107                    }
108                    Err(e) => errors.push(e),
109                }
110            }
111        }
112    }
113}