1use serde_json::{Map, Value};
10
11use crate::attrs::Attrs;
12use crate::error::DocError;
13use crate::mark::Mark;
14use crate::node::Node;
15use crate::schema::Schema;
16
17impl Mark {
18 pub fn to_json(&self) -> Value {
20 let mut obj = Map::new();
21 obj.insert("type".into(), Value::String(self.mark_type().name().into()));
22 if !self.attrs().is_empty() {
23 obj.insert(
24 "attrs".into(),
25 Value::Object(self.attrs().clone().into_iter().collect()),
26 );
27 }
28 Value::Object(obj)
29 }
30}
31
32impl Node {
33 pub fn to_json(&self) -> Value {
35 let mut obj = Map::new();
36 obj.insert("type".into(), Value::String(self.node_type().name().into()));
37 if let Some(text) = self.text() {
38 obj.insert("text".into(), Value::String(text.into()));
39 }
40 if !self.attrs().is_empty() {
41 obj.insert(
42 "attrs".into(),
43 Value::Object(self.attrs().clone().into_iter().collect()),
44 );
45 }
46 if self.child_count() > 0 {
47 let content: Vec<Value> = self.content().iter().map(Node::to_json).collect();
48 obj.insert("content".into(), Value::Array(content));
49 }
50 if !self.marks().is_empty() {
51 let marks: Vec<Value> = self.marks().iter().map(Mark::to_json).collect();
52 obj.insert("marks".into(), Value::Array(marks));
53 }
54 Value::Object(obj)
55 }
56}
57
58fn obj<'a>(v: &'a Value, ctx: &str) -> Result<&'a Map<String, Value>, DocError> {
59 v.as_object()
60 .ok_or_else(|| DocError::MalformedJson(format!("{ctx}: expected an object")))
61}
62
63fn attrs_from(v: Option<&Value>) -> Result<Attrs, DocError> {
64 match v {
65 None => Ok(Attrs::new()),
66 Some(Value::Object(m)) => Ok(m.clone().into_iter().collect()),
67 Some(_) => Err(DocError::MalformedJson("`attrs` must be an object".into())),
68 }
69}
70
71impl Schema {
72 pub fn mark_from_json(&self, v: &Value) -> Result<Mark, DocError> {
74 let m = obj(v, "mark")?;
75 let name = m
76 .get("type")
77 .and_then(Value::as_str)
78 .ok_or_else(|| DocError::MalformedJson("mark: missing `type`".into()))?;
79 let mt = self
80 .mark_type(name)
81 .ok_or_else(|| DocError::UnknownMarkType(name.to_string()))?
82 .clone();
83 Ok(mt.create(attrs_from(m.get("attrs"))?))
84 }
85
86 fn marks_from(&self, v: Option<&Value>) -> Result<Vec<Mark>, DocError> {
87 match v {
88 None => Ok(Vec::new()),
89 Some(Value::Array(a)) => a.iter().map(|m| self.mark_from_json(m)).collect(),
90 Some(_) => Err(DocError::MalformedJson("`marks` must be an array".into())),
91 }
92 }
93
94 pub fn node_from_json(&self, v: &Value) -> Result<Node, DocError> {
97 let m = obj(v, "node")?;
98 let name = m
99 .get("type")
100 .and_then(Value::as_str)
101 .ok_or_else(|| DocError::MalformedJson("node: missing `type`".into()))?;
102 let marks = self.marks_from(m.get("marks"))?;
103
104 if let Some(text) = m.get("text") {
105 let text = text
106 .as_str()
107 .ok_or_else(|| DocError::MalformedJson("`text` must be a string".into()))?;
108 return self.text(text, marks);
109 }
110
111 let children = match m.get("content") {
112 None => Vec::new(),
113 Some(Value::Array(a)) => a
114 .iter()
115 .map(|c| self.node_from_json(c))
116 .collect::<Result<Vec<_>, _>>()?,
117 Some(_) => return Err(DocError::MalformedJson("`content` must be an array".into())),
118 };
119 self.node(name, attrs_from(m.get("attrs"))?, children, marks)
120 }
121
122 pub fn parse_json_str(&self, s: &str) -> Result<Node, DocError> {
124 let v: Value =
125 serde_json::from_str(s).map_err(|e| DocError::MalformedJson(e.to_string()))?;
126 self.node_from_json(&v)
127 }
128}