ferrox_models/grammar/json_schema/
value.rs1use serde::de::{Deserializer, MapAccess, SeqAccess, Visitor};
19use serde::Deserialize;
20use std::fmt;
21use std::fmt::Write as _;
22
23#[derive(Debug, Clone, PartialEq)]
25pub enum JsonValue {
26 Null,
27 Bool(bool),
28 Number(serde_json::Number),
29 String(String),
30 Array(Vec<JsonValue>),
31 Object(Vec<(String, JsonValue)>),
32}
33
34impl JsonValue {
35 pub fn parse(text: &str) -> Result<Self, serde_json::Error> {
37 serde_json::from_str(text)
38 }
39
40 pub fn get(&self, key: &str) -> Option<&JsonValue> {
43 match self {
44 JsonValue::Object(entries) => entries.iter().find(|(k, _)| k == key).map(|(_, v)| v),
45 _ => None,
46 }
47 }
48
49 pub fn contains_key(&self, key: &str) -> bool {
51 self.get(key).is_some()
52 }
53
54 pub fn as_object(&self) -> Option<&[(String, JsonValue)]> {
55 match self {
56 JsonValue::Object(entries) => Some(entries.as_slice()),
57 _ => None,
58 }
59 }
60
61 pub fn as_array(&self) -> Option<&[JsonValue]> {
62 match self {
63 JsonValue::Array(items) => Some(items.as_slice()),
64 _ => None,
65 }
66 }
67
68 pub fn as_str(&self) -> Option<&str> {
69 match self {
70 JsonValue::String(s) => Some(s.as_str()),
71 _ => None,
72 }
73 }
74
75 pub fn as_bool(&self) -> Option<bool> {
76 match self {
77 JsonValue::Bool(b) => Some(*b),
78 _ => None,
79 }
80 }
81
82 pub fn as_u64(&self) -> Option<u64> {
84 match self {
85 JsonValue::Number(n) => n.as_u64(),
86 _ => None,
87 }
88 }
89
90 pub fn kind(&self) -> &'static str {
92 match self {
93 JsonValue::Null => "null",
94 JsonValue::Bool(_) => "boolean",
95 JsonValue::Number(_) => "number",
96 JsonValue::String(_) => "string",
97 JsonValue::Array(_) => "array",
98 JsonValue::Object(_) => "object",
99 }
100 }
101
102 pub fn dump(&self) -> String {
107 let mut out = String::new();
108 self.dump_into(&mut out);
109 out
110 }
111
112 fn dump_into(&self, out: &mut String) {
113 match self {
114 JsonValue::Null => out.push_str("null"),
115 JsonValue::Bool(true) => out.push_str("true"),
116 JsonValue::Bool(false) => out.push_str("false"),
117 JsonValue::Number(n) => {
118 let _ = write!(out, "{n}");
119 }
120 JsonValue::String(s) => escape_json_string(s, out),
121 JsonValue::Array(items) => {
122 out.push('[');
123 for (i, item) in items.iter().enumerate() {
124 if i > 0 {
125 out.push(',');
126 }
127 item.dump_into(out);
128 }
129 out.push(']');
130 }
131 JsonValue::Object(entries) => {
132 out.push('{');
133 for (i, (k, v)) in entries.iter().enumerate() {
134 if i > 0 {
135 out.push(',');
136 }
137 escape_json_string(k, out);
138 out.push(':');
139 v.dump_into(out);
140 }
141 out.push('}');
142 }
143 }
144 }
145}
146
147fn escape_json_string(s: &str, out: &mut String) {
151 out.push('"');
152 for c in s.chars() {
153 match c {
154 '"' => out.push_str("\\\""),
155 '\\' => out.push_str("\\\\"),
156 '\u{08}' => out.push_str("\\b"),
157 '\u{0c}' => out.push_str("\\f"),
158 '\n' => out.push_str("\\n"),
159 '\r' => out.push_str("\\r"),
160 '\t' => out.push_str("\\t"),
161 c if (c as u32) < 0x20 => {
162 let _ = write!(out, "\\u{:04x}", c as u32);
163 }
164 c => out.push(c),
165 }
166 }
167 out.push('"');
168}
169
170impl From<&serde_json::Value> for JsonValue {
171 fn from(value: &serde_json::Value) -> Self {
172 match value {
173 serde_json::Value::Null => JsonValue::Null,
174 serde_json::Value::Bool(b) => JsonValue::Bool(*b),
175 serde_json::Value::Number(n) => JsonValue::Number(n.clone()),
176 serde_json::Value::String(s) => JsonValue::String(s.clone()),
177 serde_json::Value::Array(items) => {
178 JsonValue::Array(items.iter().map(JsonValue::from).collect())
179 }
180 serde_json::Value::Object(map) => JsonValue::Object(
181 map.iter()
182 .map(|(k, v)| (k.clone(), JsonValue::from(v)))
183 .collect(),
184 ),
185 }
186 }
187}
188
189impl<'de> Deserialize<'de> for JsonValue {
190 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
191 deserializer.deserialize_any(JsonValueVisitor)
192 }
193}
194
195struct JsonValueVisitor;
196
197impl<'de> Visitor<'de> for JsonValueVisitor {
198 type Value = JsonValue;
199
200 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 f.write_str("any JSON value")
202 }
203
204 fn visit_unit<E>(self) -> Result<JsonValue, E> {
205 Ok(JsonValue::Null)
206 }
207
208 fn visit_none<E>(self) -> Result<JsonValue, E> {
209 Ok(JsonValue::Null)
210 }
211
212 fn visit_some<D: Deserializer<'de>>(self, d: D) -> Result<JsonValue, D::Error> {
213 d.deserialize_any(self)
214 }
215
216 fn visit_bool<E>(self, v: bool) -> Result<JsonValue, E> {
217 Ok(JsonValue::Bool(v))
218 }
219
220 fn visit_i64<E>(self, v: i64) -> Result<JsonValue, E> {
221 Ok(JsonValue::Number(v.into()))
222 }
223
224 fn visit_u64<E>(self, v: u64) -> Result<JsonValue, E> {
225 Ok(JsonValue::Number(v.into()))
226 }
227
228 fn visit_f64<E: serde::de::Error>(self, v: f64) -> Result<JsonValue, E> {
229 Ok(match serde_json::Number::from_f64(v) {
233 Some(n) => JsonValue::Number(n),
234 None => JsonValue::Null,
235 })
236 }
237
238 fn visit_str<E>(self, v: &str) -> Result<JsonValue, E> {
239 Ok(JsonValue::String(v.to_string()))
240 }
241
242 fn visit_string<E>(self, v: String) -> Result<JsonValue, E> {
243 Ok(JsonValue::String(v))
244 }
245
246 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<JsonValue, A::Error> {
247 let mut items = Vec::new();
248 while let Some(item) = seq.next_element()? {
249 items.push(item);
250 }
251 Ok(JsonValue::Array(items))
252 }
253
254 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<JsonValue, A::Error> {
255 let mut entries: Vec<(String, JsonValue)> = Vec::new();
258 while let Some((k, v)) = map.next_entry::<String, JsonValue>()? {
259 if !entries.iter().any(|(existing, _)| *existing == k) {
260 entries.push((k, v));
261 }
262 }
263 Ok(JsonValue::Object(entries))
264 }
265}