adana_script_core/primitive/
json.rs1use std::collections::BTreeMap;
2
3use anyhow::anyhow;
4use serde_json::{Value, json};
5
6use super::Primitive;
7
8pub trait Json {
9 fn from_json(s: &str) -> anyhow::Result<Self>
10 where
11 Self: Sized;
12 fn to_json(&self) -> anyhow::Result<String>;
13}
14
15fn json_to_primitive(value: Value) -> anyhow::Result<Primitive> {
16 match value {
17 Value::Null => Ok(Primitive::Null),
18 Value::Bool(b) => Ok(Primitive::Bool(b)),
19 Value::Number(number) => number
20 .as_u64()
21 .map(|n| Primitive::Int(n as i128))
22 .or(number.as_i64().map(|n| Primitive::Int(n as i128)))
23 .or(number.as_f64().map(Primitive::Double))
24 .ok_or(anyhow!("could not parse json number")),
25 Value::String(s) => Ok(Primitive::String(s)),
26 Value::Array(json_array) => {
27 let mut prim_array = Vec::with_capacity(json_array.len());
28 for v in json_array {
29 prim_array.push(json_to_primitive(v)?);
30 }
31 Ok(Primitive::Array(prim_array))
32 }
33 Value::Object(o) => {
34 let mut struct_array = BTreeMap::new();
35 for (k, v) in o {
36 struct_array.insert(k, json_to_primitive(v)?);
37 }
38 Ok(Primitive::Struct(struct_array))
39 }
40 }
41}
42fn primitive_to_value(p: &Primitive) -> anyhow::Result<Value> {
43 match p {
44 Primitive::Ref(r) => {
45 let r =
46 r.read().map_err(|e| anyhow!("could not acquire lock! {e}"))?;
47 primitive_to_value(&r)
48 }
49 Primitive::U8(u) => Ok(json!(u)),
50 Primitive::I8(u) => Ok(json!(u)),
51 Primitive::Int(u) => Ok(json!(u)),
52 Primitive::Double(u) => Ok(json!(u)),
53 Primitive::Bool(b) => Ok(json!(b)),
54 Primitive::Null => Ok(Value::Null),
55 Primitive::String(s) => Ok(Value::String(s.to_owned())),
56 Primitive::Array(prim_arr) => {
57 let mut json_arr = Vec::with_capacity(prim_arr.len());
58 for p in prim_arr {
59 json_arr.push(primitive_to_value(p)?);
60 }
61 Ok(Value::Array(json_arr))
62 }
63 Primitive::Struct(s) => {
64 let mut o = serde_json::Map::with_capacity(s.len());
65 for (k, v) in s {
66 o.insert(k.to_string(), primitive_to_value(v)?);
67 }
68 Ok(Value::Object(o))
69 }
70 v => Ok(json!(v.to_string())),
71 }
72}
73
74impl Json for Primitive {
75 fn from_json(s: &str) -> anyhow::Result<Self> {
76 let value = serde_json::from_str(s)?;
77 json_to_primitive(value)
78 }
79
80 fn to_json(&self) -> anyhow::Result<String> {
81 let value = primitive_to_value(self)?;
82 serde_json::to_string_pretty(&value).map_err(|e| anyhow!("{e}"))
83 }
84}