blob: 82a0f7d80845b32b4d204e42254156bb5e36dc99 [file] [log] [blame]
Elly Jones656a2af2011-11-07 23:24:441// Rust JSON serialization library
2// Copyright (c) 2011 Google Inc.
Elly Jonesbd726262011-11-07 19:01:283
Gareth Daniel Smithbe014162012-07-04 21:53:124//! json serialization
Brian Anderson95521c42012-03-08 02:17:305
Brian Anderson47d468f2012-03-16 22:14:376import result::{result, ok, err};
Erick Tryzelaar012dec52012-02-26 00:39:327import io;
8import io::{reader_util, writer_util};
Elly Jonesbd726262011-11-07 19:01:289import map;
Patrick Waltonc9375fe2012-03-08 00:48:5710import map::hashmap;
Patrick Waltondb020ab2012-07-11 22:00:4011import map::map;
Patrick Waltonf093d372012-05-22 17:54:1212import core::vec::extensions;
Elly Jonesbd726262011-11-07 19:01:2813
14export json;
Erick Tryzelaarfaccd4a2012-03-05 16:47:2115export error;
Erick Tryzelaar012dec52012-02-26 00:39:3216export to_writer;
Elly Jones656a2af2011-11-07 23:24:4417export to_str;
Erick Tryzelaar012dec52012-02-26 00:39:3218export from_reader;
Elly Jones656a2af2011-11-07 23:24:4419export from_str;
Erick Tryzelaar012dec52012-02-26 00:39:3220export eq;
Erick Tryzelaared5af702012-05-28 19:10:3221export to_json;
Elly Jonesbd726262011-11-07 19:01:2822
Elly Jones656a2af2011-11-07 23:24:4423export num;
24export string;
25export boolean;
26export list;
27export dict;
Erick Tryzelaar012dec52012-02-26 00:39:3228export null;
Elly Jones656a2af2011-11-07 23:24:4429
Gareth Daniel Smithbe014162012-07-04 21:53:1230/// Represents a json value
Patrick Waltonc5a407b2012-01-19 23:20:5731enum json {
Patrick Walton194d8e32012-01-20 01:55:3432 num(float),
Michael Sullivan92743dc2012-07-14 05:57:4833 string(@~str),
Patrick Walton194d8e32012-01-20 01:55:3434 boolean(bool),
Michael Sullivan98e161f2012-06-29 23:26:5635 list(@~[json]),
Michael Sullivan92743dc2012-07-14 05:57:4836 dict(map::hashmap<~str, json>),
Patrick Walton194d8e32012-01-20 01:55:3437 null,
Elly Jonesbd726262011-11-07 19:01:2838}
39
Erick Tryzelaar012dec52012-02-26 00:39:3240type error = {
41 line: uint,
42 col: uint,
Michael Sullivan92743dc2012-07-14 05:57:4843 msg: @~str,
Erick Tryzelaar012dec52012-02-26 00:39:3244};
45
Gareth Daniel Smithbe014162012-07-04 21:53:1246/// Serializes a json value into a io::writer
Erick Tryzelaar012dec52012-02-26 00:39:3247fn to_writer(wr: io::writer, j: json) {
48 alt j {
Brian Anderson025d8662012-08-04 02:59:0449 num(n) => wr.write_str(float::to_str(n, 6u)),
50 string(s) => wr.write_str(escape_str(*s)),
51 boolean(b) => wr.write_str(if b { ~"true" } else { ~"false" }),
52 list(v) => {
Erick Tryzelaar012dec52012-02-26 00:39:3253 wr.write_char('[');
Niko Matsakis6b358752012-03-14 18:03:5654 let mut first = true;
Brian Andersond1fc2b52012-06-30 23:19:0755 for (*v).each |item| {
Erick Tryzelaar012dec52012-02-26 00:39:3256 if !first {
Michael Sullivan92743dc2012-07-14 05:57:4857 wr.write_str(~", ");
Erick Tryzelaar012dec52012-02-26 00:39:3258 }
59 first = false;
60 to_writer(wr, item);
61 };
62 wr.write_char(']');
63 }
Brian Anderson025d8662012-08-04 02:59:0464 dict(d) => {
Erick Tryzelaar012dec52012-02-26 00:39:3265 if d.size() == 0u {
Michael Sullivan92743dc2012-07-14 05:57:4866 wr.write_str(~"{}");
Brian Andersonb3559362012-08-02 00:30:0567 return;
Erick Tryzelaar012dec52012-02-26 00:39:3268 }
69
Michael Sullivan92743dc2012-07-14 05:57:4870 wr.write_str(~"{ ");
Niko Matsakis6b358752012-03-14 18:03:5671 let mut first = true;
Brian Andersond1fc2b52012-06-30 23:19:0772 for d.each |key, value| {
Erick Tryzelaar012dec52012-02-26 00:39:3273 if !first {
Michael Sullivan92743dc2012-07-14 05:57:4874 wr.write_str(~", ");
Erick Tryzelaar012dec52012-02-26 00:39:3275 }
76 first = false;
Erick Tryzelaarb361f6c2012-06-13 00:20:5177 wr.write_str(escape_str(key));
Michael Sullivan92743dc2012-07-14 05:57:4878 wr.write_str(~": ");
Erick Tryzelaar012dec52012-02-26 00:39:3279 to_writer(wr, value);
80 };
Michael Sullivan92743dc2012-07-14 05:57:4881 wr.write_str(~" }");
Erick Tryzelaar012dec52012-02-26 00:39:3282 }
Brian Anderson025d8662012-08-04 02:59:0483 null => wr.write_str(~"null")
Erick Tryzelaar012dec52012-02-26 00:39:3284 }
85}
86
Michael Sullivan92743dc2012-07-14 05:57:4887fn escape_str(s: ~str) -> ~str {
88 let mut escaped = ~"\"";
Brian Andersond1fc2b52012-06-30 23:19:0789 do str::chars_iter(s) |c| {
Erick Tryzelaarb361f6c2012-06-13 00:20:5190 alt c {
Brian Anderson025d8662012-08-04 02:59:0491 '"' => escaped += ~"\\\"",
92 '\\' => escaped += ~"\\\\",
93 '\x08' => escaped += ~"\\b",
94 '\x0c' => escaped += ~"\\f",
95 '\n' => escaped += ~"\\n",
96 '\r' => escaped += ~"\\r",
97 '\t' => escaped += ~"\\t",
98 _ => escaped += str::from_char(c)
Erick Tryzelaarb361f6c2012-06-13 00:20:5199 }
100 };
101
Michael Sullivan92743dc2012-07-14 05:57:48102 escaped += ~"\"";
Erick Tryzelaarb361f6c2012-06-13 00:20:51103
104 escaped
105}
106
Gareth Daniel Smithbe014162012-07-04 21:53:12107/// Serializes a json value into a string
Michael Sullivan92743dc2012-07-14 05:57:48108fn to_str(j: json) -> ~str {
Brian Andersond1fc2b52012-06-30 23:19:07109 io::with_str_writer(|wr| to_writer(wr, j))
Elly Jonesbd726262011-11-07 19:01:28110}
111
Patrick Waltondb020ab2012-07-11 22:00:40112type parser_ = {
Erick Tryzelaar012dec52012-02-26 00:39:32113 rdr: io::reader,
Graydon Hoare6e6798c2012-03-27 01:35:18114 mut ch: char,
115 mut line: uint,
116 mut col: uint,
Erick Tryzelaar012dec52012-02-26 00:39:32117};
Elly Jonesbd726262011-11-07 19:01:28118
Patrick Waltondb020ab2012-07-11 22:00:40119enum parser {
120 parser_(parser_)
121}
122
Erick Tryzelaar012dec52012-02-26 00:39:32123impl parser for parser {
124 fn eof() -> bool { self.ch == -1 as char }
Elly Jonesbd726262011-11-07 19:01:28125
Erick Tryzelaar012dec52012-02-26 00:39:32126 fn bump() {
127 self.ch = self.rdr.read_char();
128
129 if self.ch == '\n' {
130 self.line += 1u;
131 self.col = 1u;
132 } else {
133 self.col += 1u;
134 }
Elly Jonesbd726262011-11-07 19:01:28135 }
136
Erick Tryzelaar012dec52012-02-26 00:39:32137 fn next_char() -> char {
138 self.bump();
139 self.ch
Elly Jonesbd726262011-11-07 19:01:28140 }
141
Michael Sullivan92743dc2012-07-14 05:57:48142 fn error<T>(+msg: ~str) -> result<T, error> {
Erick Tryzelaarb361f6c2012-06-13 00:20:51143 err({ line: self.line, col: self.col, msg: @msg })
Elly Jonesbd726262011-11-07 19:01:28144 }
Elly Jonesbd726262011-11-07 19:01:28145
Brian Andersonb968c8e2012-03-13 21:39:28146 fn parse() -> result<json, error> {
Erick Tryzelaar012dec52012-02-26 00:39:32147 alt self.parse_value() {
Brian Anderson025d8662012-08-04 02:59:04148 ok(value) => {
Tycho Sciecf87c32012-02-29 08:47:17149 // Skip trailing whitespaces.
150 self.parse_whitespace();
Erick Tryzelaar012dec52012-02-26 00:39:32151 // Make sure there is no trailing characters.
152 if self.eof() {
153 ok(value)
154 } else {
Michael Sullivan92743dc2012-07-14 05:57:48155 self.error(~"trailing characters")
Erick Tryzelaar012dec52012-02-26 00:39:32156 }
157 }
Brian Anderson025d8662012-08-04 02:59:04158 e => e
Elly Jonesbd726262011-11-07 19:01:28159 }
Elly Jonesbd726262011-11-07 19:01:28160 }
Elly Jonesbd726262011-11-07 19:01:28161
Brian Andersonb968c8e2012-03-13 21:39:28162 fn parse_value() -> result<json, error> {
Erick Tryzelaar012dec52012-02-26 00:39:32163 self.parse_whitespace();
Elly Jonesbd726262011-11-07 19:01:28164
Brian Andersonb3559362012-08-02 00:30:05165 if self.eof() { return self.error(~"EOF while parsing value"); }
Erick Tryzelaar012dec52012-02-26 00:39:32166
167 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04168 'n' => self.parse_ident(~"ull", null),
169 't' => self.parse_ident(~"rue", boolean(true)),
170 'f' => self.parse_ident(~"alse", boolean(false)),
171 '0' to '9' | '-' => self.parse_number(),
172 '"' => alt self.parse_str() {
173 ok(s) => ok(string(s)),
174 err(e) => err(e)
Erick Tryzelaar012dec52012-02-26 00:39:32175 }
Brian Anderson025d8662012-08-04 02:59:04176 '[' => self.parse_list(),
177 '{' => self.parse_object(),
178 _ => self.error(~"invalid syntax")
Erick Tryzelaar012dec52012-02-26 00:39:32179 }
180 }
181
182 fn parse_whitespace() {
183 while char::is_whitespace(self.ch) { self.bump(); }
184 }
185
Michael Sullivan92743dc2012-07-14 05:57:48186 fn parse_ident(ident: ~str, value: json) -> result<json, error> {
Brian Andersond1fc2b52012-06-30 23:19:07187 if str::all(ident, |c| c == self.next_char()) {
Erick Tryzelaar012dec52012-02-26 00:39:32188 self.bump();
189 ok(value)
190 } else {
Michael Sullivan92743dc2012-07-14 05:57:48191 self.error(~"invalid syntax")
Erick Tryzelaar012dec52012-02-26 00:39:32192 }
193 }
194
Brian Andersonb968c8e2012-03-13 21:39:28195 fn parse_number() -> result<json, error> {
Niko Matsakis6b358752012-03-14 18:03:56196 let mut neg = 1f;
Erick Tryzelaar012dec52012-02-26 00:39:32197
198 if self.ch == '-' {
199 self.bump();
Marijn Haverbeke4f826d82011-12-16 09:11:00200 neg = -1f;
Elly Jonesbd726262011-11-07 19:01:28201 }
Elly Jonesbd726262011-11-07 19:01:28202
Niko Matsakis6b358752012-03-14 18:03:56203 let mut res = alt self.parse_integer() {
Brian Anderson025d8662012-08-04 02:59:04204 ok(res) => res,
205 err(e) => return err(e)
Erick Tryzelaar012dec52012-02-26 00:39:32206 };
207
208 if self.ch == '.' {
209 alt self.parse_decimal(res) {
Brian Anderson025d8662012-08-04 02:59:04210 ok(r) => res = r,
211 err(e) => return err(e)
Elly Jonesbd726262011-11-07 19:01:28212 }
Elly Jonesbd726262011-11-07 19:01:28213 }
Erick Tryzelaar012dec52012-02-26 00:39:32214
215 if self.ch == 'e' || self.ch == 'E' {
216 alt self.parse_exponent(res) {
Brian Anderson025d8662012-08-04 02:59:04217 ok(r) => res = r,
218 err(e) => return err(e)
Erick Tryzelaar012dec52012-02-26 00:39:32219 }
220 }
221
222 ok(num(neg * res))
Elly Jonesbd726262011-11-07 19:01:28223 }
224
Brian Andersonb968c8e2012-03-13 21:39:28225 fn parse_integer() -> result<float, error> {
Niko Matsakis6b358752012-03-14 18:03:56226 let mut res = 0f;
Erick Tryzelaar012dec52012-02-26 00:39:32227
228 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04229 '0' => {
Erick Tryzelaar012dec52012-02-26 00:39:32230 self.bump();
231
232 // There can be only one leading '0'.
233 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04234 '0' to '9' => return self.error(~"invalid number"),
235 _ => ()
Erick Tryzelaar012dec52012-02-26 00:39:32236 }
237 }
Brian Anderson025d8662012-08-04 02:59:04238 '1' to '9' => {
Erick Tryzelaar012dec52012-02-26 00:39:32239 while !self.eof() {
240 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04241 '0' to '9' => {
Erick Tryzelaar012dec52012-02-26 00:39:32242 res *= 10f;
243 res += ((self.ch as int) - ('0' as int)) as float;
244
245 self.bump();
246 }
Brian Anderson025d8662012-08-04 02:59:04247 _ => break
Erick Tryzelaar012dec52012-02-26 00:39:32248 }
249 }
250 }
Brian Anderson025d8662012-08-04 02:59:04251 _ => return self.error(~"invalid number")
Erick Tryzelaar012dec52012-02-26 00:39:32252 }
253
254 ok(res)
Elly Jonesbd726262011-11-07 19:01:28255 }
256
Brian Andersonb968c8e2012-03-13 21:39:28257 fn parse_decimal(res: float) -> result<float, error> {
Erick Tryzelaar012dec52012-02-26 00:39:32258 self.bump();
259
260 // Make sure a digit follows the decimal place.
261 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04262 '0' to '9' => (),
263 _ => return self.error(~"invalid number")
Erick Tryzelaar012dec52012-02-26 00:39:32264 }
265
Niko Matsakis6b358752012-03-14 18:03:56266 let mut res = res;
267 let mut dec = 1f;
Erick Tryzelaar012dec52012-02-26 00:39:32268 while !self.eof() {
269 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04270 '0' to '9' => {
Marijn Haverbeke4f826d82011-12-16 09:11:00271 dec /= 10f;
Erick Tryzelaar012dec52012-02-26 00:39:32272 res += (((self.ch as int) - ('0' as int)) as float) * dec;
273
274 self.bump();
275 }
Brian Anderson025d8662012-08-04 02:59:04276 _ => break
Elly Jonesbd726262011-11-07 19:01:28277 }
Elly Jonesbd726262011-11-07 19:01:28278 }
Elly Jonesbd726262011-11-07 19:01:28279
Erick Tryzelaar012dec52012-02-26 00:39:32280 ok(res)
281 }
282
Brian Andersonb968c8e2012-03-13 21:39:28283 fn parse_exponent(res: float) -> result<float, error> {
Erick Tryzelaar012dec52012-02-26 00:39:32284 self.bump();
285
Niko Matsakis6b358752012-03-14 18:03:56286 let mut res = res;
287 let mut exp = 0u;
288 let mut neg_exp = false;
Erick Tryzelaar012dec52012-02-26 00:39:32289
290 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04291 '+' => self.bump(),
292 '-' => { self.bump(); neg_exp = true; }
293 _ => ()
Erick Tryzelaar012dec52012-02-26 00:39:32294 }
295
296 // Make sure a digit follows the exponent place.
297 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04298 '0' to '9' => (),
299 _ => return self.error(~"invalid number")
Erick Tryzelaar012dec52012-02-26 00:39:32300 }
301
302 while !self.eof() {
303 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04304 '0' to '9' => {
Erick Tryzelaar012dec52012-02-26 00:39:32305 exp *= 10u;
306 exp += (self.ch as uint) - ('0' as uint);
307
308 self.bump();
309 }
Brian Anderson025d8662012-08-04 02:59:04310 _ => break
Erick Tryzelaar012dec52012-02-26 00:39:32311 }
312 }
313
314 let exp = float::pow_with_uint(10u, exp);
315 if neg_exp {
316 res /= exp;
317 } else {
318 res *= exp;
319 }
320
321 ok(res)
322 }
323
Michael Sullivan92743dc2012-07-14 05:57:48324 fn parse_str() -> result<@~str, error> {
Niko Matsakis6b358752012-03-14 18:03:56325 let mut escape = false;
Michael Sullivan92743dc2012-07-14 05:57:48326 let mut res = ~"";
Erick Tryzelaar012dec52012-02-26 00:39:32327
328 while !self.eof() {
329 self.bump();
330
331 if (escape) {
332 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04333 '"' => str::push_char(res, '"'),
334 '\\' => str::push_char(res, '\\'),
335 '/' => str::push_char(res, '/'),
336 'b' => str::push_char(res, '\x08'),
337 'f' => str::push_char(res, '\x0c'),
338 'n' => str::push_char(res, '\n'),
339 'r' => str::push_char(res, '\r'),
340 't' => str::push_char(res, '\t'),
341 'u' => {
Erick Tryzelaar012dec52012-02-26 00:39:32342 // Parse \u1234.
Niko Matsakis6b358752012-03-14 18:03:56343 let mut i = 0u;
344 let mut n = 0u;
Erick Tryzelaar012dec52012-02-26 00:39:32345 while i < 4u {
346 alt self.next_char() {
Brian Anderson025d8662012-08-04 02:59:04347 '0' to '9' => {
Erick Tryzelaar012dec52012-02-26 00:39:32348 n = n * 10u +
349 (self.ch as uint) - ('0' as uint);
350 }
Brian Anderson025d8662012-08-04 02:59:04351 _ => return self.error(~"invalid \\u escape")
Erick Tryzelaar012dec52012-02-26 00:39:32352 }
Niko Matsakis6b358752012-03-14 18:03:56353 i += 1u;
Erick Tryzelaar012dec52012-02-26 00:39:32354 }
355
356 // Error out if we didn't parse 4 digits.
357 if i != 4u {
Brian Andersonb3559362012-08-02 00:30:05358 return self.error(~"invalid \\u escape");
Erick Tryzelaar012dec52012-02-26 00:39:32359 }
360
361 str::push_char(res, n as char);
362 }
Brian Anderson025d8662012-08-04 02:59:04363 _ => return self.error(~"invalid escape")
Erick Tryzelaar012dec52012-02-26 00:39:32364 }
365 escape = false;
366 } else if self.ch == '\\' {
367 escape = true;
368 } else {
369 if self.ch == '"' {
370 self.bump();
Brian Andersonb3559362012-08-02 00:30:05371 return ok(@res);
Erick Tryzelaar012dec52012-02-26 00:39:32372 }
373 str::push_char(res, self.ch);
374 }
375 }
376
Michael Sullivan92743dc2012-07-14 05:57:48377 self.error(~"EOF while parsing string")
Erick Tryzelaar012dec52012-02-26 00:39:32378 }
379
Brian Andersonb968c8e2012-03-13 21:39:28380 fn parse_list() -> result<json, error> {
Erick Tryzelaar012dec52012-02-26 00:39:32381 self.bump();
382 self.parse_whitespace();
383
Michael Sullivan98e161f2012-06-29 23:26:56384 let mut values = ~[];
Erick Tryzelaar012dec52012-02-26 00:39:32385
386 if self.ch == ']' {
387 self.bump();
Brian Andersonb3559362012-08-02 00:30:05388 return ok(list(@values));
Erick Tryzelaar012dec52012-02-26 00:39:32389 }
390
Tim Chevalier35400e12012-03-11 04:34:17391 loop {
Erick Tryzelaar012dec52012-02-26 00:39:32392 alt self.parse_value() {
Brian Anderson025d8662012-08-04 02:59:04393 ok(v) => vec::push(values, v),
394 e => return e
Erick Tryzelaar012dec52012-02-26 00:39:32395 }
396
397 self.parse_whitespace();
Tim Chevalier35400e12012-03-11 04:34:17398 if self.eof() {
Brian Andersonb3559362012-08-02 00:30:05399 return self.error(~"EOF while parsing list");
Tim Chevalier35400e12012-03-11 04:34:17400 }
Erick Tryzelaar012dec52012-02-26 00:39:32401
402 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04403 ',' => self.bump(),
404 ']' => { self.bump(); return ok(list(@values)); }
405 _ => return self.error(~"expected `,` or `]`")
Erick Tryzelaar012dec52012-02-26 00:39:32406 }
Tim Chevalier35400e12012-03-11 04:34:17407 };
Erick Tryzelaar012dec52012-02-26 00:39:32408 }
409
Brian Andersonb968c8e2012-03-13 21:39:28410 fn parse_object() -> result<json, error> {
Erick Tryzelaar012dec52012-02-26 00:39:32411 self.bump();
412 self.parse_whitespace();
413
Brian Anderson3864d6d2012-03-14 19:07:23414 let values = map::str_hash();
Erick Tryzelaar012dec52012-02-26 00:39:32415
416 if self.ch == '}' {
417 self.bump();
Brian Andersonb3559362012-08-02 00:30:05418 return ok(dict(values));
Erick Tryzelaar012dec52012-02-26 00:39:32419 }
420
421 while !self.eof() {
422 self.parse_whitespace();
423
424 if self.ch != '"' {
Brian Andersonb3559362012-08-02 00:30:05425 return self.error(~"key must be a string");
Erick Tryzelaar012dec52012-02-26 00:39:32426 }
427
428 let key = alt self.parse_str() {
Brian Anderson025d8662012-08-04 02:59:04429 ok(key) => key,
430 err(e) => return err(e)
Erick Tryzelaar012dec52012-02-26 00:39:32431 };
432
433 self.parse_whitespace();
434
435 if self.ch != ':' {
436 if self.eof() { break; }
Brian Andersonb3559362012-08-02 00:30:05437 return self.error(~"expected `:`");
Erick Tryzelaar012dec52012-02-26 00:39:32438 }
439 self.bump();
440
441 alt self.parse_value() {
Brian Anderson025d8662012-08-04 02:59:04442 ok(value) => { values.insert(copy *key, value); }
443 e => return e
Erick Tryzelaar012dec52012-02-26 00:39:32444 }
445 self.parse_whitespace();
446
447 alt self.ch {
Brian Anderson025d8662012-08-04 02:59:04448 ',' => self.bump(),
449 '}' => { self.bump(); return ok(dict(values)); }
450 _ => {
Erick Tryzelaar012dec52012-02-26 00:39:32451 if self.eof() { break; }
Brian Andersonb3559362012-08-02 00:30:05452 return self.error(~"expected `,` or `}`");
Erick Tryzelaar012dec52012-02-26 00:39:32453 }
454 }
455 }
456
Brian Andersonb3559362012-08-02 00:30:05457 return self.error(~"EOF while parsing object");
Elly Jonesbd726262011-11-07 19:01:28458 }
459}
460
Gareth Daniel Smithbe014162012-07-04 21:53:12461/// Deserializes a json value from an io::reader
Brian Andersonb968c8e2012-03-13 21:39:28462fn from_reader(rdr: io::reader) -> result<json, error> {
Patrick Waltondb020ab2012-07-11 22:00:40463 let parser = parser_({
Erick Tryzelaar012dec52012-02-26 00:39:32464 rdr: rdr,
Graydon Hoare6e6798c2012-03-27 01:35:18465 mut ch: rdr.read_char(),
466 mut line: 1u,
467 mut col: 1u,
Patrick Waltondb020ab2012-07-11 22:00:40468 });
Erick Tryzelaar012dec52012-02-26 00:39:32469
470 parser.parse()
Elly Jonesbd726262011-11-07 19:01:28471}
472
Gareth Daniel Smithbe014162012-07-04 21:53:12473/// Deserializes a json value from a string
Michael Sullivan92743dc2012-07-14 05:57:48474fn from_str(s: ~str) -> result<json, error> {
Erick Tryzelaar1404a862012-02-29 18:48:57475 io::with_str_reader(s, from_reader)
Erick Tryzelaar012dec52012-02-26 00:39:32476}
477
Gareth Daniel Smithbe014162012-07-04 21:53:12478/// Test if two json values are equal
Erick Tryzelaar012dec52012-02-26 00:39:32479fn eq(value0: json, value1: json) -> bool {
480 alt (value0, value1) {
Brian Anderson025d8662012-08-04 02:59:04481 (num(f0), num(f1)) => f0 == f1,
482 (string(s0), string(s1)) => s0 == s1,
483 (boolean(b0), boolean(b1)) => b0 == b1,
484 (list(l0), list(l1)) => vec::all2(*l0, *l1, eq),
485 (dict(d0), dict(d1)) => {
Erick Tryzelaar012dec52012-02-26 00:39:32486 if d0.size() == d1.size() {
Niko Matsakis6b358752012-03-14 18:03:56487 let mut equal = true;
Brian Andersond1fc2b52012-06-30 23:19:07488 for d0.each |k, v0| {
Erick Tryzelaar012dec52012-02-26 00:39:32489 alt d1.find(k) {
Brian Anderson025d8662012-08-04 02:59:04490 some(v1) => if !eq(v0, v1) { equal = false },
491 none => equal = false
Erick Tryzelaar012dec52012-02-26 00:39:32492 }
493 };
494 equal
495 } else {
496 false
497 }
498 }
Brian Anderson025d8662012-08-04 02:59:04499 (null, null) => true,
500 _ => false
Erick Tryzelaar012dec52012-02-26 00:39:32501 }
Elly Jonesbd726262011-11-07 19:01:28502}
Brian Anderson6e27b272012-01-18 03:05:07503
Lindsey Kuper439afaa2012-07-31 17:27:51504trait to_json { fn to_json() -> json; }
Erick Tryzelaared5af702012-05-28 19:10:32505
506impl of to_json for json {
507 fn to_json() -> json { self }
508}
509
Erick Tryzelaar11a56c32012-06-13 15:30:54510impl of to_json for @json {
511 fn to_json() -> json { *self }
512}
513
514impl of to_json for int {
515 fn to_json() -> json { num(self as float) }
516}
517
Erick Tryzelaared5af702012-05-28 19:10:32518impl of to_json for i8 {
519 fn to_json() -> json { num(self as float) }
520}
521
522impl of to_json for i16 {
523 fn to_json() -> json { num(self as float) }
524}
525
526impl of to_json for i32 {
527 fn to_json() -> json { num(self as float) }
528}
529
530impl of to_json for i64 {
531 fn to_json() -> json { num(self as float) }
532}
533
Erick Tryzelaar11a56c32012-06-13 15:30:54534impl of to_json for uint {
535 fn to_json() -> json { num(self as float) }
536}
537
Erick Tryzelaared5af702012-05-28 19:10:32538impl of to_json for u8 {
539 fn to_json() -> json { num(self as float) }
540}
541
542impl of to_json for u16 {
543 fn to_json() -> json { num(self as float) }
544}
545
546impl of to_json for u32 {
547 fn to_json() -> json { num(self as float) }
548}
549
550impl of to_json for u64 {
551 fn to_json() -> json { num(self as float) }
552}
553
554impl of to_json for float {
555 fn to_json() -> json { num(self) }
556}
557
558impl of to_json for f32 {
559 fn to_json() -> json { num(self as float) }
560}
561
562impl of to_json for f64 {
563 fn to_json() -> json { num(self as float) }
564}
565
566impl of to_json for () {
567 fn to_json() -> json { null }
568}
569
570impl of to_json for bool {
571 fn to_json() -> json { boolean(self) }
572}
573
Michael Sullivan92743dc2012-07-14 05:57:48574impl of to_json for ~str {
Erick Tryzelaarb361f6c2012-06-13 00:20:51575 fn to_json() -> json { string(@copy self) }
576}
577
Michael Sullivan92743dc2012-07-14 05:57:48578impl of to_json for @~str {
Erick Tryzelaared5af702012-05-28 19:10:32579 fn to_json() -> json { string(self) }
580}
581
Niko Matsakis97452c02012-08-02 22:42:56582impl <A: to_json, B: to_json> of to_json for (A, B) {
Erick Tryzelaared5af702012-05-28 19:10:32583 fn to_json() -> json {
Niko Matsakis97452c02012-08-02 22:42:56584 alt self {
585 (a, b) => {
586 list(@~[a.to_json(), b.to_json()])
587 }
588 }
Erick Tryzelaared5af702012-05-28 19:10:32589 }
590}
591
Niko Matsakis97452c02012-08-02 22:42:56592impl <A: to_json, B: to_json, C: to_json>
Erick Tryzelaared5af702012-05-28 19:10:32593 of to_json for (A, B, C) {
594 fn to_json() -> json {
Niko Matsakis97452c02012-08-02 22:42:56595 alt self {
596 (a, b, c) => {
597 list(@~[a.to_json(), b.to_json(), c.to_json()])
598 }
599 }
Erick Tryzelaared5af702012-05-28 19:10:32600 }
601}
602
Michael Sullivan98e161f2012-06-29 23:26:56603impl <A: to_json> of to_json for ~[A] {
Brian Andersond1fc2b52012-06-30 23:19:07604 fn to_json() -> json { list(@self.map(|elt| elt.to_json())) }
Erick Tryzelaared5af702012-05-28 19:10:32605}
606
Michael Sullivan92743dc2012-07-14 05:57:48607impl <A: to_json copy> of to_json for hashmap<~str, A> {
Erick Tryzelaared5af702012-05-28 19:10:32608 fn to_json() -> json {
609 let d = map::str_hash();
Brian Andersond1fc2b52012-06-30 23:19:07610 for self.each() |key, value| {
Erick Tryzelaarb361f6c2012-06-13 00:20:51611 d.insert(copy key, value.to_json());
Erick Tryzelaared5af702012-05-28 19:10:32612 }
613 dict(d)
614 }
615}
616
617impl <A: to_json> of to_json for option<A> {
618 fn to_json() -> json {
619 alt self {
Brian Anderson025d8662012-08-04 02:59:04620 none => null,
621 some(value) => value.to_json()
Erick Tryzelaared5af702012-05-28 19:10:32622 }
623 }
624}
625
626impl of to_str::to_str for json {
Michael Sullivan92743dc2012-07-14 05:57:48627 fn to_str() -> ~str { to_str(self) }
Erick Tryzelaared5af702012-05-28 19:10:32628}
629
Erick Tryzelaara8161762012-06-11 15:32:38630impl of to_str::to_str for error {
Michael Sullivan92743dc2012-07-14 05:57:48631 fn to_str() -> ~str {
Paul Stansifera9cc5062012-07-30 23:01:07632 fmt!{"%u:%u: %s", self.line, self.col, *self.msg}
Erick Tryzelaara8161762012-06-11 15:32:38633 }
634}
635
Brian Anderson6e27b272012-01-18 03:05:07636#[cfg(test)]
637mod tests {
Michael Sullivan92743dc2012-07-14 05:57:48638 fn mk_dict(items: ~[(~str, json)]) -> json {
Brian Anderson3864d6d2012-03-14 19:07:23639 let d = map::str_hash();
Erick Tryzelaar012dec52012-02-26 00:39:32640
Brian Andersond1fc2b52012-06-30 23:19:07641 do vec::iter(items) |item| {
Erick Tryzelaarb361f6c2012-06-13 00:20:51642 let (key, value) = copy item;
Erick Tryzelaar012dec52012-02-26 00:39:32643 d.insert(key, value);
644 };
645
646 dict(d)
Brian Anderson6e27b272012-01-18 03:05:07647 }
648
649 #[test]
Erick Tryzelaar012dec52012-02-26 00:39:32650 fn test_write_null() {
Michael Sullivan92743dc2012-07-14 05:57:48651 assert to_str(null) == ~"null";
Brian Anderson6e27b272012-01-18 03:05:07652 }
653
654 #[test]
Erick Tryzelaar012dec52012-02-26 00:39:32655 fn test_write_num() {
Michael Sullivan92743dc2012-07-14 05:57:48656 assert to_str(num(3f)) == ~"3";
657 assert to_str(num(3.1f)) == ~"3.1";
658 assert to_str(num(-1.5f)) == ~"-1.5";
659 assert to_str(num(0.5f)) == ~"0.5";
Brian Anderson6e27b272012-01-18 03:05:07660 }
661
662 #[test]
Erick Tryzelaar012dec52012-02-26 00:39:32663 fn test_write_str() {
Michael Sullivan92743dc2012-07-14 05:57:48664 assert to_str(string(@~"")) == ~"\"\"";
665 assert to_str(string(@~"foo")) == ~"\"foo\"";
Brian Anderson6e27b272012-01-18 03:05:07666 }
667
668 #[test]
Erick Tryzelaar012dec52012-02-26 00:39:32669 fn test_write_bool() {
Michael Sullivan92743dc2012-07-14 05:57:48670 assert to_str(boolean(true)) == ~"true";
671 assert to_str(boolean(false)) == ~"false";
Brian Anderson6e27b272012-01-18 03:05:07672 }
673
674 #[test]
Erick Tryzelaar012dec52012-02-26 00:39:32675 fn test_write_list() {
Michael Sullivan92743dc2012-07-14 05:57:48676 assert to_str(list(@~[])) == ~"[]";
677 assert to_str(list(@~[boolean(true)])) == ~"[true]";
Michael Sullivan98e161f2012-06-29 23:26:56678 assert to_str(list(@~[
Erick Tryzelaar012dec52012-02-26 00:39:32679 boolean(false),
680 null,
Michael Sullivan92743dc2012-07-14 05:57:48681 list(@~[string(@~"foo\nbar"), num(3.5f)])
682 ])) == ~"[false, null, [\"foo\\nbar\", 3.5]]";
Erick Tryzelaar012dec52012-02-26 00:39:32683 }
684
685 #[test]
686 fn test_write_dict() {
Michael Sullivan92743dc2012-07-14 05:57:48687 assert to_str(mk_dict(~[])) == ~"{}";
688 assert to_str(mk_dict(~[(~"a", boolean(true))]))
689 == ~"{ \"a\": true }";
Michael Sullivan98e161f2012-06-29 23:26:56690 assert to_str(mk_dict(~[
Michael Sullivan92743dc2012-07-14 05:57:48691 (~"a", boolean(true)),
692 (~"b", list(@~[
693 mk_dict(~[(~"c", string(@~"\x0c\r"))]),
694 mk_dict(~[(~"d", string(@~""))])
Michael Sullivan98e161f2012-06-29 23:26:56695 ]))
696 ])) ==
Michael Sullivan92743dc2012-07-14 05:57:48697 ~"{ " +
698 ~"\"a\": true, " +
699 ~"\"b\": [" +
700 ~"{ \"c\": \"\\f\\r\" }, " +
701 ~"{ \"d\": \"\" }" +
702 ~"]" +
703 ~" }";
Erick Tryzelaar012dec52012-02-26 00:39:32704 }
705
706 #[test]
707 fn test_trailing_characters() {
Michael Sullivan92743dc2012-07-14 05:57:48708 assert from_str(~"nulla") ==
709 err({line: 1u, col: 5u, msg: @~"trailing characters"});
710 assert from_str(~"truea") ==
711 err({line: 1u, col: 5u, msg: @~"trailing characters"});
712 assert from_str(~"falsea") ==
713 err({line: 1u, col: 6u, msg: @~"trailing characters"});
714 assert from_str(~"1a") ==
715 err({line: 1u, col: 2u, msg: @~"trailing characters"});
716 assert from_str(~"[]a") ==
717 err({line: 1u, col: 3u, msg: @~"trailing characters"});
718 assert from_str(~"{}a") ==
719 err({line: 1u, col: 3u, msg: @~"trailing characters"});
Erick Tryzelaar012dec52012-02-26 00:39:32720 }
721
722 #[test]
723 fn test_read_identifiers() {
Michael Sullivan92743dc2012-07-14 05:57:48724 assert from_str(~"n") ==
725 err({line: 1u, col: 2u, msg: @~"invalid syntax"});
726 assert from_str(~"nul") ==
727 err({line: 1u, col: 4u, msg: @~"invalid syntax"});
Erick Tryzelaar012dec52012-02-26 00:39:32728
Michael Sullivan92743dc2012-07-14 05:57:48729 assert from_str(~"t") ==
730 err({line: 1u, col: 2u, msg: @~"invalid syntax"});
731 assert from_str(~"truz") ==
732 err({line: 1u, col: 4u, msg: @~"invalid syntax"});
Erick Tryzelaar012dec52012-02-26 00:39:32733
Michael Sullivan92743dc2012-07-14 05:57:48734 assert from_str(~"f") ==
735 err({line: 1u, col: 2u, msg: @~"invalid syntax"});
736 assert from_str(~"faz") ==
737 err({line: 1u, col: 3u, msg: @~"invalid syntax"});
Erick Tryzelaar012dec52012-02-26 00:39:32738
Michael Sullivan92743dc2012-07-14 05:57:48739 assert from_str(~"null") == ok(null);
740 assert from_str(~"true") == ok(boolean(true));
741 assert from_str(~"false") == ok(boolean(false));
742 assert from_str(~" null ") == ok(null);
743 assert from_str(~" true ") == ok(boolean(true));
744 assert from_str(~" false ") == ok(boolean(false));
Erick Tryzelaar012dec52012-02-26 00:39:32745 }
746
747 #[test]
748 fn test_read_num() {
Michael Sullivan92743dc2012-07-14 05:57:48749 assert from_str(~"+") ==
750 err({line: 1u, col: 1u, msg: @~"invalid syntax"});
751 assert from_str(~".") ==
752 err({line: 1u, col: 1u, msg: @~"invalid syntax"});
Erick Tryzelaar012dec52012-02-26 00:39:32753
Michael Sullivan92743dc2012-07-14 05:57:48754 assert from_str(~"-") ==
755 err({line: 1u, col: 2u, msg: @~"invalid number"});
756 assert from_str(~"00") ==
757 err({line: 1u, col: 2u, msg: @~"invalid number"});
758 assert from_str(~"1.") ==
759 err({line: 1u, col: 3u, msg: @~"invalid number"});
760 assert from_str(~"1e") ==
761 err({line: 1u, col: 3u, msg: @~"invalid number"});
762 assert from_str(~"1e+") ==
763 err({line: 1u, col: 4u, msg: @~"invalid number"});
Erick Tryzelaar012dec52012-02-26 00:39:32764
Michael Sullivan92743dc2012-07-14 05:57:48765 assert from_str(~"3") == ok(num(3f));
766 assert from_str(~"3.1") == ok(num(3.1f));
767 assert from_str(~"-1.2") == ok(num(-1.2f));
768 assert from_str(~"0.4") == ok(num(0.4f));
769 assert from_str(~"0.4e5") == ok(num(0.4e5f));
770 assert from_str(~"0.4e+15") == ok(num(0.4e15f));
771 assert from_str(~"0.4e-01") == ok(num(0.4e-01f));
772 assert from_str(~" 3 ") == ok(num(3f));
Erick Tryzelaar012dec52012-02-26 00:39:32773 }
774
775 #[test]
776 fn test_read_str() {
Michael Sullivan92743dc2012-07-14 05:57:48777 assert from_str(~"\"") ==
778 err({line: 1u, col: 2u, msg: @~"EOF while parsing string"});
779 assert from_str(~"\"lol") ==
780 err({line: 1u, col: 5u, msg: @~"EOF while parsing string"});
Erick Tryzelaar012dec52012-02-26 00:39:32781
Michael Sullivan92743dc2012-07-14 05:57:48782 assert from_str(~"\"\"") == ok(string(@~""));
783 assert from_str(~"\"foo\"") == ok(string(@~"foo"));
784 assert from_str(~"\"\\\"\"") == ok(string(@~"\""));
785 assert from_str(~"\"\\b\"") == ok(string(@~"\x08"));
786 assert from_str(~"\"\\n\"") == ok(string(@~"\n"));
787 assert from_str(~"\"\\r\"") == ok(string(@~"\r"));
788 assert from_str(~"\"\\t\"") == ok(string(@~"\t"));
789 assert from_str(~" \"foo\" ") == ok(string(@~"foo"));
Erick Tryzelaar012dec52012-02-26 00:39:32790 }
791
792 #[test]
793 fn test_read_list() {
Michael Sullivan92743dc2012-07-14 05:57:48794 assert from_str(~"[") ==
795 err({line: 1u, col: 2u, msg: @~"EOF while parsing value"});
796 assert from_str(~"[1") ==
797 err({line: 1u, col: 3u, msg: @~"EOF while parsing list"});
798 assert from_str(~"[1,") ==
799 err({line: 1u, col: 4u, msg: @~"EOF while parsing value"});
800 assert from_str(~"[1,]") ==
801 err({line: 1u, col: 4u, msg: @~"invalid syntax"});
802 assert from_str(~"[6 7]") ==
803 err({line: 1u, col: 4u, msg: @~"expected `,` or `]`"});
Erick Tryzelaar012dec52012-02-26 00:39:32804
Michael Sullivan92743dc2012-07-14 05:57:48805 assert from_str(~"[]") == ok(list(@~[]));
806 assert from_str(~"[ ]") == ok(list(@~[]));
807 assert from_str(~"[true]") == ok(list(@~[boolean(true)]));
808 assert from_str(~"[ false ]") == ok(list(@~[boolean(false)]));
809 assert from_str(~"[null]") == ok(list(@~[null]));
810 assert from_str(~"[3, 1]") == ok(list(@~[num(3f), num(1f)]));
811 assert from_str(~"\n[3, 2]\n") == ok(list(@~[num(3f), num(2f)]));
812 assert from_str(~"[2, [4, 1]]") ==
Michael Sullivan98e161f2012-06-29 23:26:56813 ok(list(@~[num(2f), list(@~[num(4f), num(1f)])]));
Erick Tryzelaar012dec52012-02-26 00:39:32814 }
815
816 #[test]
817 fn test_read_dict() {
Michael Sullivan92743dc2012-07-14 05:57:48818 assert from_str(~"{") ==
819 err({line: 1u, col: 2u, msg: @~"EOF while parsing object"});
820 assert from_str(~"{ ") ==
821 err({line: 1u, col: 3u, msg: @~"EOF while parsing object"});
822 assert from_str(~"{1") ==
823 err({line: 1u, col: 2u, msg: @~"key must be a string"});
824 assert from_str(~"{ \"a\"") ==
825 err({line: 1u, col: 6u, msg: @~"EOF while parsing object"});
826 assert from_str(~"{\"a\"") ==
827 err({line: 1u, col: 5u, msg: @~"EOF while parsing object"});
828 assert from_str(~"{\"a\" ") ==
829 err({line: 1u, col: 6u, msg: @~"EOF while parsing object"});
Erick Tryzelaar012dec52012-02-26 00:39:32830
Michael Sullivan92743dc2012-07-14 05:57:48831 assert from_str(~"{\"a\" 1") ==
832 err({line: 1u, col: 6u, msg: @~"expected `:`"});
833 assert from_str(~"{\"a\":") ==
834 err({line: 1u, col: 6u, msg: @~"EOF while parsing value"});
835 assert from_str(~"{\"a\":1") ==
836 err({line: 1u, col: 7u, msg: @~"EOF while parsing object"});
837 assert from_str(~"{\"a\":1 1") ==
838 err({line: 1u, col: 8u, msg: @~"expected `,` or `}`"});
839 assert from_str(~"{\"a\":1,") ==
840 err({line: 1u, col: 8u, msg: @~"EOF while parsing object"});
Erick Tryzelaar012dec52012-02-26 00:39:32841
Michael Sullivan92743dc2012-07-14 05:57:48842 assert eq(result::get(from_str(~"{}")), mk_dict(~[]));
843 assert eq(result::get(from_str(~"{\"a\": 3}")),
844 mk_dict(~[(~"a", num(3.0f))]));
Erick Tryzelaar012dec52012-02-26 00:39:32845
Michael Sullivan92743dc2012-07-14 05:57:48846 assert eq(result::get(from_str(~"{ \"a\": null, \"b\" : true }")),
Michael Sullivan98e161f2012-06-29 23:26:56847 mk_dict(~[
Michael Sullivan92743dc2012-07-14 05:57:48848 (~"a", null),
849 (~"b", boolean(true))]));
850 assert eq(result::get(from_str(~"\n{ \"a\": null, \"b\" : true }\n")),
Michael Sullivan98e161f2012-06-29 23:26:56851 mk_dict(~[
Michael Sullivan92743dc2012-07-14 05:57:48852 (~"a", null),
853 (~"b", boolean(true))]));
854 assert eq(result::get(from_str(~"{\"a\" : 1.0 ,\"b\": [ true ]}")),
Michael Sullivan98e161f2012-06-29 23:26:56855 mk_dict(~[
Michael Sullivan92743dc2012-07-14 05:57:48856 (~"a", num(1.0)),
857 (~"b", list(@~[boolean(true)]))
Michael Sullivan98e161f2012-06-29 23:26:56858 ]));
Erick Tryzelaar012dec52012-02-26 00:39:32859 assert eq(result::get(from_str(
Michael Sullivan92743dc2012-07-14 05:57:48860 ~"{" +
861 ~"\"a\": 1.0, " +
862 ~"\"b\": [" +
863 ~"true," +
864 ~"\"foo\\nbar\", " +
865 ~"{ \"c\": {\"d\": null} } " +
866 ~"]" +
867 ~"}")),
Michael Sullivan98e161f2012-06-29 23:26:56868 mk_dict(~[
Michael Sullivan92743dc2012-07-14 05:57:48869 (~"a", num(1.0f)),
870 (~"b", list(@~[
Erick Tryzelaar012dec52012-02-26 00:39:32871 boolean(true),
Michael Sullivan92743dc2012-07-14 05:57:48872 string(@~"foo\nbar"),
Michael Sullivan98e161f2012-06-29 23:26:56873 mk_dict(~[
Michael Sullivan92743dc2012-07-14 05:57:48874 (~"c", mk_dict(~[(~"d", null)]))
Michael Sullivan98e161f2012-06-29 23:26:56875 ])
876 ]))
877 ]));
Erick Tryzelaar012dec52012-02-26 00:39:32878 }
879
880 #[test]
881 fn test_multiline_errors() {
Michael Sullivan92743dc2012-07-14 05:57:48882 assert from_str(~"{\n \"foo\":\n \"bar\"") ==
883 err({line: 3u, col: 8u, msg: @~"EOF while parsing object"});
Brian Anderson6e27b272012-01-18 03:05:07884 }
885}