1use serde_json::{Map, Value};
6
7pub fn to_json(v: &yog_data::Value) -> Value {
9 match v {
10 yog_data::Value::Null => Value::Null,
11 yog_data::Value::Bool(b) => Value::Bool(*b),
12 yog_data::Value::Int(n) => Value::from(*n),
13 yog_data::Value::Float(f) => serde_json::Number::from_f64(*f).map_or(Value::Null, Value::Number),
14 yog_data::Value::Str(s) => Value::String(s.clone()),
15 yog_data::Value::List(items) => Value::Array(items.iter().map(to_json).collect()),
16 yog_data::Value::Map(m) => Value::Object(m.iter().map(|(k, v)| (k.to_string(), to_json(v))).collect()),
17 typed => Value::String(yog_data::typed::typed_string(typed).unwrap_or_default()),
18 }
19}
20
21pub fn from_json(v: &Value) -> yog_data::Value {
23 match v {
24 Value::Null => yog_data::Value::Null,
25 Value::Bool(b) => yog_data::Value::Bool(*b),
26 Value::Number(n) => n.as_i64().map_or_else(|| yog_data::Value::Float(n.as_f64().unwrap_or(0.0)), yog_data::Value::Int),
27 Value::String(s) => yog_data::Value::Str(s.clone()),
28 Value::Array(items) => yog_data::Value::List(items.iter().map(from_json).collect()),
29 Value::Object(m) => {
30 let mut out = yog_data::Map::new();
31 for (k, v) in m {
32 out.insert(k.as_str(), from_json(v));
33 }
34 yog_data::Value::Map(out)
35 }
36 }
37}
38
39pub fn read_object(text: &str) -> Option<Map<String, Value>> {
41 match to_json(&yog_data::text::parse_value(text).ok()?) {
42 Value::Object(m) => Some(m),
43 _ => None,
44 }
45}
46
47pub fn runtime_ids(v: &mut Value) {
50 match v {
51 Value::String(s) if s.starts_with('@') => match yog_data::typed::classify(s) {
52 Ok(yog_data::Value::Ref(r)) => *s = r.id,
53 Ok(yog_data::Value::Tag(r)) => *s = format!("#{}", r.id),
54 Ok(yog_data::Value::Str(plain)) => *s = plain,
55 _ => {}
56 },
57 Value::Array(items) => items.iter_mut().for_each(runtime_ids),
58 Value::Object(m) => m.values_mut().for_each(runtime_ids),
59 _ => {}
60 }
61}
62
63pub fn at<'a>(v: &'a Value, keys: &[&str]) -> Option<&'a Value> {
65 keys.iter().try_fold(v, |v, k| v.get(*k))
66}