1 use crate::JsonValue;
2 use std::collections::HashMap;
3 use std::fmt;
4 use std::io::{self, Write};
5
6 /// Serialization error. This error only happens when some write error happens on writing the serialized byte sequence
7 /// to the given `io::Write` object.
8 #[derive(Debug)]
9 pub struct JsonGenerateError {
10 msg: String,
11 }
12
13 impl JsonGenerateError {
message(&self) -> &str14 pub fn message(&self) -> &str {
15 self.msg.as_str()
16 }
17 }
18
19 impl fmt::Display for JsonGenerateError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 write!(f, "Generate error: {}", &self.msg)
22 }
23 }
24
25 impl std::error::Error for JsonGenerateError {}
26
27 /// Convenient type alias for serialization results.
28 pub type JsonGenerateResult = Result<String, JsonGenerateError>;
29
30 /// JSON serializer for `JsonValue`.
31 ///
32 /// Basically you don't need to use this struct directly since `JsonValue::stringify` or `JsonValue::format` methods are
33 /// using this internally.
34 ///
35 /// ```
36 /// use tinyjson::{JsonGenerator, JsonValue};
37 ///
38 /// let v = JsonValue::from("hello, world".to_string());
39 /// let mut buf = vec![];
40 /// let mut gen = JsonGenerator::new(&mut buf);
41 /// gen.generate(&v).unwrap();
42 ///
43 /// assert_eq!(String::from_utf8(buf).unwrap(), "\"hello, world\"");
44 /// ```
45 pub struct JsonGenerator<'indent, W: Write> {
46 out: W,
47 indent: Option<&'indent str>,
48 }
49
50 impl<'indent, W: Write> JsonGenerator<'indent, W> {
51 /// Create a new `JsonGenerator` object. The serialized byte sequence will be written to the given `io::Write`
52 /// object.
new(out: W) -> Self53 pub fn new(out: W) -> Self {
54 Self { out, indent: None }
55 }
56
57 /// Set indent string. This will be used by [`JsonGenerator::generate`].
58 /// ```
59 /// use tinyjson::{JsonGenerator, JsonValue};
60 ///
61 /// let v = JsonValue::from(vec![1.0.into(), 2.0.into(), 3.0.into()]);
62 /// let mut buf = vec![];
63 /// let mut gen = JsonGenerator::new(&mut buf).indent(" ");
64 /// gen.generate(&v).unwrap();
65 ///
66 /// assert_eq!(String::from_utf8(buf).unwrap(),
67 /// "[
68 /// 1,
69 /// 2,
70 /// 3
71 /// ]");
72 /// ```
indent(mut self, indent: &'indent str) -> Self73 pub fn indent(mut self, indent: &'indent str) -> Self {
74 self.indent = Some(indent);
75 self
76 }
77
quote(&mut self, s: &str) -> io::Result<()>78 fn quote(&mut self, s: &str) -> io::Result<()> {
79 const B: u8 = b'b'; // \x08
80 const T: u8 = b't'; // \x09
81 const N: u8 = b'n'; // \x0a
82 const F: u8 = b'f'; // \x0c
83 const R: u8 = b'r'; // \x0d
84 const Q: u8 = b'"'; // \x22
85 const S: u8 = b'\\'; // \x5c
86 const U: u8 = 1; // non-printable
87
88 #[rustfmt::skip]
89 const ESCAPE_TABLE: [u8; 256] = [
90 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
91 U, U, U, U, U, U, U, U, B, T, N, U, F, R, U, U, // 0
92 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, // 1
93 0, 0, Q, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
94 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
95 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
96 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, S, 0, 0, 0, // 5
97 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
98 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F
107 ];
108
109 self.out.write_all(b"\"")?;
110 let mut start = 0;
111 for (i, c) in s.char_indices() {
112 let u = c as usize;
113 if u < 256 {
114 let esc = ESCAPE_TABLE[u];
115 if esc == 0 {
116 continue;
117 }
118 if start != i {
119 self.out.write_all(s[start..i].as_bytes())?;
120 }
121 if esc == U {
122 write!(self.out, "\\u{:04x}", u)?;
123 } else {
124 self.out.write_all(&[b'\\', esc])?;
125 }
126 start = i + 1;
127 }
128 }
129 if start != s.len() {
130 self.out.write_all(s[start..].as_bytes())?;
131 }
132 self.out.write_all(b"\"")
133 }
134
number(&mut self, f: f64) -> io::Result<()>135 fn number(&mut self, f: f64) -> io::Result<()> {
136 if f.is_infinite() {
137 Err(io::Error::new(
138 io::ErrorKind::Other,
139 "JSON cannot represent inf",
140 ))
141 } else if f.is_nan() {
142 Err(io::Error::new(
143 io::ErrorKind::Other,
144 "JSON cannot represent NaN",
145 ))
146 } else {
147 write!(self.out, "{}", f)
148 }
149 }
150
encode_array(&mut self, array: &[JsonValue]) -> io::Result<()>151 fn encode_array(&mut self, array: &[JsonValue]) -> io::Result<()> {
152 self.out.write_all(b"[")?;
153 let mut first = true;
154 for elem in array.iter() {
155 if first {
156 first = false;
157 } else {
158 self.out.write_all(b",")?;
159 }
160 self.encode(elem)?;
161 }
162 self.out.write_all(b"]")
163 }
164
encode_object(&mut self, m: &HashMap<String, JsonValue>) -> io::Result<()>165 fn encode_object(&mut self, m: &HashMap<String, JsonValue>) -> io::Result<()> {
166 self.out.write_all(b"{")?;
167 let mut first = true;
168 for (k, v) in m {
169 if first {
170 first = false;
171 } else {
172 self.out.write_all(b",")?;
173 }
174 self.quote(k)?;
175 self.out.write_all(b":")?;
176 self.encode(v)?;
177 }
178 self.out.write_all(b"}")
179 }
180
encode(&mut self, value: &JsonValue) -> io::Result<()>181 fn encode(&mut self, value: &JsonValue) -> io::Result<()> {
182 match value {
183 JsonValue::Number(n) => self.number(*n),
184 JsonValue::Boolean(b) => write!(self.out, "{}", *b),
185 JsonValue::String(s) => self.quote(s),
186 JsonValue::Null => self.out.write_all(b"null"),
187 JsonValue::Array(a) => self.encode_array(a),
188 JsonValue::Object(o) => self.encode_object(o),
189 }
190 }
191
write_indent(&mut self, indent: &str, level: usize) -> io::Result<()>192 fn write_indent(&mut self, indent: &str, level: usize) -> io::Result<()> {
193 for _ in 0..level {
194 self.out.write_all(indent.as_bytes())?;
195 }
196 Ok(())
197 }
198
format_array(&mut self, array: &[JsonValue], indent: &str, level: usize) -> io::Result<()>199 fn format_array(&mut self, array: &[JsonValue], indent: &str, level: usize) -> io::Result<()> {
200 if array.is_empty() {
201 return self.out.write_all(b"[]");
202 }
203
204 self.out.write_all(b"[\n")?;
205 let mut first = true;
206 for elem in array.iter() {
207 if first {
208 first = false;
209 } else {
210 self.out.write_all(b",\n")?;
211 }
212 self.write_indent(indent, level + 1)?;
213 self.format(elem, indent, level + 1)?;
214 }
215 self.out.write_all(b"\n")?;
216 self.write_indent(indent, level)?;
217 self.out.write_all(b"]")
218 }
219
format_object( &mut self, m: &HashMap<String, JsonValue>, indent: &str, level: usize, ) -> io::Result<()>220 fn format_object(
221 &mut self,
222 m: &HashMap<String, JsonValue>,
223 indent: &str,
224 level: usize,
225 ) -> io::Result<()> {
226 if m.is_empty() {
227 return self.out.write_all(b"{}");
228 }
229
230 self.out.write_all(b"{\n")?;
231 let mut first = true;
232 for (k, v) in m {
233 if first {
234 first = false;
235 } else {
236 self.out.write_all(b",\n")?;
237 }
238 self.write_indent(indent, level + 1)?;
239 self.quote(k)?;
240 self.out.write_all(b": ")?;
241 self.format(v, indent, level + 1)?;
242 }
243 self.out.write_all(b"\n")?;
244 self.write_indent(indent, level)?;
245 self.out.write_all(b"}")
246 }
247
format(&mut self, value: &JsonValue, indent: &str, level: usize) -> io::Result<()>248 fn format(&mut self, value: &JsonValue, indent: &str, level: usize) -> io::Result<()> {
249 match value {
250 JsonValue::Number(n) => self.number(*n),
251 JsonValue::Boolean(b) => write!(self.out, "{}", *b),
252 JsonValue::String(s) => self.quote(s),
253 JsonValue::Null => self.out.write_all(b"null"),
254 JsonValue::Array(a) => self.format_array(a, indent, level),
255 JsonValue::Object(o) => self.format_object(o, indent, level),
256 }
257 }
258
259 /// Serialize the `JsonValue` into UTF-8 byte sequence. The result will be written to the `io::Write` object passed
260 /// at [`JsonGenerator::new`].
261 /// This method serializes the value without indentation by default. But after setting an indent string via
262 /// [`JsonGenerator::indent`], this method will use the indent for elements of array and object.
263 ///
264 /// ```
265 /// use tinyjson::{JsonGenerator, JsonValue};
266 ///
267 /// let v = JsonValue::from(vec![1.0.into(), 2.0.into(), 3.0.into()]);
268 ///
269 /// let mut buf = vec![];
270 /// let mut gen = JsonGenerator::new(&mut buf);
271 /// gen.generate(&v).unwrap();
272 /// assert_eq!(String::from_utf8(buf).unwrap(), "[1,2,3]");
273 ///
274 /// let mut buf = vec![];
275 /// let mut gen = JsonGenerator::new(&mut buf).indent(" "); // with 2-spaces indent
276 /// gen.generate(&v).unwrap();
277 ///
278 /// assert_eq!(String::from_utf8(buf).unwrap(),
279 /// "[
280 /// 1,
281 /// 2,
282 /// 3
283 /// ]");
284 /// ```
generate(&mut self, value: &JsonValue) -> io::Result<()>285 pub fn generate(&mut self, value: &JsonValue) -> io::Result<()> {
286 if let Some(indent) = &self.indent {
287 self.format(value, indent, 0)
288 } else {
289 self.encode(value)
290 }
291 }
292 }
293
294 /// Serialize the given `JsonValue` value to `String` without indentation. This method is almost identical to
295 /// `JsonValue::stringify` but exists for a historical reason.
296 ///
297 /// ```
298 /// use tinyjson::JsonValue;
299 ///
300 /// let v = JsonValue::from(vec![1.0.into(), 2.0.into(), 3.0.into()]);
301 /// let s = tinyjson::stringify(&v).unwrap();
302 /// assert_eq!(s, "[1,2,3]");
303 /// ```
stringify(value: &JsonValue) -> JsonGenerateResult304 pub fn stringify(value: &JsonValue) -> JsonGenerateResult {
305 let mut to = Vec::new();
306 let mut gen = JsonGenerator::new(&mut to);
307 gen.generate(value).map_err(|err| JsonGenerateError {
308 msg: format!("{}", err),
309 })?;
310 Ok(String::from_utf8(to).unwrap())
311 }
312
313 /// Serialize the given `JsonValue` value to `String` with 2-spaces indentation. This method is almost identical to
314 /// `JsonValue::format` but exists for a historical reason.
315 ///
316 /// ```
317 /// use tinyjson::JsonValue;
318 ///
319 /// let v = JsonValue::from(vec![1.0.into(), 2.0.into(), 3.0.into()]);
320 /// let s = tinyjson::format(&v).unwrap();
321 /// assert_eq!(s, "[\n 1,\n 2,\n 3\n]");
322 /// ```
format(value: &JsonValue) -> JsonGenerateResult323 pub fn format(value: &JsonValue) -> JsonGenerateResult {
324 let mut to = Vec::new();
325 let mut gen = JsonGenerator::new(&mut to).indent(" ");
326 gen.generate(value).map_err(|err| JsonGenerateError {
327 msg: format!("{}", err),
328 })?;
329 Ok(String::from_utf8(to).unwrap())
330 }
331