1#![cfg_attr(not(feature = "std"), no_std)]
52#![forbid(unsafe_code)]
53#![warn(missing_docs)]
54
55extern crate alloc;
56
57#[cfg(feature = "canonical")]
58mod canonical;
59mod error;
60mod limits;
61mod number;
62mod parse;
63#[cfg(feature = "primitives")]
64mod primitives;
65mod value;
66mod write;
67
68#[cfg(feature = "canonical")]
69pub use canonical::{to_canonical_string, to_canonical_vec};
70pub use error::{
71 JsonError, JsonErrorKind, JsonLimitKind, JsonNumberError, JsonPath, JsonPathSegment,
72};
73pub use limits::JsonLimits;
74pub use number::JsonNumber;
75pub use parse::{parse, parse_str, parse_with_limits};
76#[cfg(feature = "primitives")]
77pub use primitives::{JsonExtractError, JsonExtractErrorKind};
78pub use value::{JsonMember, JsonObject, JsonValue};
79pub use write::{to_compact_string, to_compact_vec};
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use alloc::string::{String, ToString};
85
86 fn parse_ok(input: &str) -> JsonValue {
87 parse_str(input).expect("should parse")
88 }
89
90 fn kind(input: &str) -> JsonErrorKind {
91 parse_str(input).expect_err("should fail").kind().clone()
92 }
93
94 #[test]
97 fn parses_scalars() {
98 assert_eq!(parse_ok("null"), JsonValue::Null);
99 assert_eq!(parse_ok("true"), JsonValue::Bool(true));
100 assert_eq!(parse_ok("false"), JsonValue::Bool(false));
101 assert_eq!(parse_ok("\"hi\"").as_str(), Some("hi"));
102 assert_eq!(parse_ok("42").as_number().unwrap().to_i64().unwrap(), 42);
103 }
104
105 #[test]
106 fn whitespace_is_allowed_around_values() {
107 assert_eq!(parse_ok(" \t\r\n 7 \n").as_number().unwrap().as_str(), "7");
108 }
109
110 #[test]
111 fn only_json_whitespace_is_accepted() {
112 assert_eq!(kind("\u{0B}1"), JsonErrorKind::UnexpectedByte);
114 }
115
116 #[test]
119 fn parses_object_and_array() {
120 let value = parse_ok(r#"{"a":[1,2,3],"b":{"c":null}}"#);
121 let obj = value.as_object().unwrap();
122 assert_eq!(obj.len(), 2);
123 assert_eq!(obj.get("a").unwrap().as_array().unwrap().len(), 3);
124 assert!(obj
125 .get("b")
126 .unwrap()
127 .as_object()
128 .unwrap()
129 .get("c")
130 .unwrap()
131 .is_null());
132 }
133
134 #[test]
135 fn empty_containers() {
136 assert_eq!(parse_ok("[]").as_array().unwrap().len(), 0);
137 assert_eq!(parse_ok("{}").as_object().unwrap().len(), 0);
138 }
139
140 #[test]
143 fn rejects_trailing_data() {
144 assert_eq!(kind("1 2"), JsonErrorKind::TrailingData);
145 assert_eq!(kind("{} x"), JsonErrorKind::TrailingData);
146 }
147
148 #[test]
149 fn rejects_comments_and_trailing_commas() {
150 assert_eq!(kind("1 // c"), JsonErrorKind::TrailingData);
151 assert_eq!(kind("[1,]"), JsonErrorKind::UnexpectedByte);
152 assert_eq!(kind(r#"{"a":1,}"#), JsonErrorKind::UnexpectedByte);
153 }
154
155 #[test]
156 fn rejects_bad_numbers() {
157 for bad in ["01", "1.", "-", "1e", "1e+", "00", "1.2.3"] {
158 assert_eq!(kind(bad), JsonErrorKind::InvalidNumber, "input {bad:?}");
159 }
160 assert_eq!(kind(".5"), JsonErrorKind::UnexpectedByte);
163 assert_eq!(kind("+1"), JsonErrorKind::UnexpectedByte);
164 assert_eq!(kind("0x1"), JsonErrorKind::TrailingData);
165 }
166
167 #[test]
168 fn rejects_nan_and_infinity() {
169 assert_eq!(kind("NaN"), JsonErrorKind::UnexpectedByte);
170 assert_eq!(kind("Infinity"), JsonErrorKind::UnexpectedByte);
171 assert_eq!(kind("-Infinity"), JsonErrorKind::InvalidNumber);
172 }
173
174 #[test]
175 fn rejects_unescaped_control_and_bad_escapes() {
176 assert_eq!(kind("\"\u{01}\""), JsonErrorKind::UnescapedControlCharacter);
177 assert_eq!(kind(r#""\x""#), JsonErrorKind::InvalidEscape);
178 assert_eq!(kind(r#""\u00""#), JsonErrorKind::InvalidUnicodeEscape);
179 }
180
181 #[test]
182 fn rejects_lone_surrogates() {
183 assert_eq!(kind(r#""\uD800""#), JsonErrorKind::LoneSurrogate);
184 assert_eq!(kind(r#""\uDC00""#), JsonErrorKind::LoneSurrogate);
185 assert_eq!(kind(r#""\uD800a""#), JsonErrorKind::LoneSurrogate);
186 }
187
188 #[test]
189 fn accepts_valid_surrogate_pair() {
190 assert_eq!(parse_ok(r#""𝄞""#).as_str(), Some("\u{1D11E}"));
191 }
192
193 #[test]
194 fn rejects_invalid_utf8_and_bom() {
195 assert_eq!(
196 parse(&[0xff]).unwrap_err().kind().clone(),
197 JsonErrorKind::InvalidUtf8
198 );
199 assert_eq!(
200 parse(&[0xEF, 0xBB, 0xBF, b'1']).unwrap_err().kind().clone(),
201 JsonErrorKind::InvalidUtf8
202 );
203 }
204
205 #[test]
208 fn escape_and_literal_decode_equally() {
209 assert_eq!(parse_ok(r#""a""#), parse_ok(r#""a""#));
210 }
211
212 #[test]
213 fn decodes_named_escapes() {
214 assert_eq!(
215 parse_ok(r#""\n\t\r\b\f\"\\\/""#).as_str(),
216 Some("\n\t\r\u{08}\u{0C}\"\\/")
217 );
218 }
219
220 #[test]
223 fn rejects_duplicate_keys() {
224 assert_eq!(kind(r#"{"a":1,"a":2}"#), JsonErrorKind::DuplicateKey);
225 }
226
227 #[test]
228 fn duplicate_detection_is_after_escape_decoding() {
229 assert_eq!(
230 kind(r#"{"role":"user","role":"admin"}"#),
231 JsonErrorKind::DuplicateKey
232 );
233 }
234
235 #[test]
238 fn enforces_depth_limit() {
239 let limits = JsonLimits::new().with_max_depth(3);
240 assert!(parse_with_limits(b"[[[1]]]", limits).is_ok());
241 assert_eq!(
242 parse_with_limits(b"[[[[1]]]]", limits)
243 .unwrap_err()
244 .kind()
245 .clone(),
246 JsonErrorKind::LimitExceeded(JsonLimitKind::Depth)
247 );
248 }
249
250 #[test]
251 fn enforces_count_limits() {
252 let limits = JsonLimits::new();
253 let limits = JsonLimits {
254 max_array_items: 2,
255 max_object_members: 2,
256 max_total_nodes: 100,
257 ..limits
258 };
259 assert_eq!(
260 parse_with_limits(b"[1,2,3]", limits)
261 .unwrap_err()
262 .kind()
263 .clone(),
264 JsonErrorKind::LimitExceeded(JsonLimitKind::ArrayItems)
265 );
266 assert_eq!(
267 parse_with_limits(br#"{"a":1,"b":2,"c":3}"#, limits)
268 .unwrap_err()
269 .kind()
270 .clone(),
271 JsonErrorKind::LimitExceeded(JsonLimitKind::ObjectMembers)
272 );
273 }
274
275 #[test]
276 fn enforces_total_nodes_and_input_bytes() {
277 let nodes = JsonLimits::new().with_max_total_nodes(2);
278 assert_eq!(
279 parse_with_limits(b"[1,2]", nodes)
280 .unwrap_err()
281 .kind()
282 .clone(),
283 JsonErrorKind::LimitExceeded(JsonLimitKind::TotalNodes)
284 );
285 let bytes = JsonLimits::new().with_max_input_bytes(2);
286 assert_eq!(
287 parse_with_limits(b"[1]", bytes).unwrap_err().kind().clone(),
288 JsonErrorKind::LimitExceeded(JsonLimitKind::InputBytes)
289 );
290 }
291
292 #[test]
293 fn enforces_string_and_number_byte_limits() {
294 let s = JsonLimits {
295 max_string_bytes: 3,
296 ..JsonLimits::new()
297 };
298 assert_eq!(
299 parse_with_limits(br#""abcd""#, s)
300 .unwrap_err()
301 .kind()
302 .clone(),
303 JsonErrorKind::LimitExceeded(JsonLimitKind::StringBytes)
304 );
305 let n = JsonLimits {
306 max_number_bytes: 2,
307 ..JsonLimits::new()
308 };
309 assert_eq!(
310 parse_with_limits(b"12345", n).unwrap_err().kind().clone(),
311 JsonErrorKind::LimitExceeded(JsonLimitKind::NumberBytes)
312 );
313 }
314
315 #[test]
318 fn number_conversions() {
319 assert_eq!(parse_ok("-7").as_number().unwrap().to_i64().unwrap(), -7);
320 assert_eq!(parse_ok("7").as_number().unwrap().to_u64().unwrap(), 7);
321 assert!((parse_ok("1.5").as_number().unwrap().to_f64().unwrap() - 1.5).abs() < 1e-12);
322 assert_eq!(
323 parse_ok("1.5").as_number().unwrap().to_i64(),
324 Err(JsonNumberError::NotAnInteger)
325 );
326 assert_eq!(
327 parse_ok("99999999999999999999999")
328 .as_number()
329 .unwrap()
330 .to_i64(),
331 Err(JsonNumberError::OutOfRange)
332 );
333 assert_eq!(
334 parse_ok("1e400").as_number().unwrap().to_f64(),
335 Err(JsonNumberError::NotFinite)
336 );
337 }
338
339 #[test]
340 fn number_preserves_representation() {
341 assert_eq!(parse_ok("1.0").as_number().unwrap().as_str(), "1.0");
342 assert_ne!(parse_ok("1.0"), parse_ok("1")); }
344
345 #[test]
346 fn json_number_from_f64() {
347 assert_eq!(JsonNumber::try_from_f64(1.5).unwrap().as_str(), "1.5");
348 assert_eq!(
349 JsonNumber::try_from_f64(f64::NAN),
350 Err(JsonNumberError::NotFinite)
351 );
352 assert_eq!(
353 JsonNumber::try_from_f64(f64::INFINITY),
354 Err(JsonNumberError::NotFinite)
355 );
356 assert_eq!(JsonNumber::new("01"), Err(JsonNumberError::InvalidNumber));
357 }
358
359 #[test]
362 fn error_reports_location_and_path() {
363 let err = parse_str(" @").unwrap_err();
364 assert_eq!(err.kind().clone(), JsonErrorKind::UnexpectedByte);
365 assert_eq!(err.offset(), 2);
366 assert_eq!(err.line(), 1);
367 assert_eq!(err.column(), 3);
368
369 let err = parse_str(r#"{"users":[{"name":1},{"name":}]}"#).unwrap_err();
370 let path = err.path().unwrap().to_string();
371 assert_eq!(path, "$.users[1].name");
372 }
373
374 #[test]
377 fn compact_roundtrip_and_golden_bytes() {
378 let value = parse_ok(r#"{"a":1,"b":true,"c":[null,"x"]}"#);
379 assert_eq!(
380 to_compact_vec(&value),
381 br#"{"a":1,"b":true,"c":[null,"x"]}"#
382 );
383 let again = parse_str(&to_compact_string(&value)).unwrap();
385 assert_eq!(value, again);
386 }
387
388 #[test]
389 fn writer_escapes_control_and_special_characters() {
390 let mut object = JsonObject::new();
391 object.insert(
392 String::from("k"),
393 JsonValue::String(String::from("a\nb\"c\\\u{01}")),
394 );
395 let value = JsonValue::Object(object);
396 assert_eq!(to_compact_string(&value), r#"{"k":"a\nb\"c\\\u0001"}"#);
397 }
398
399 #[test]
400 fn object_insert_replaces_in_place() {
401 let mut object = JsonObject::new();
402 assert!(object
403 .insert(String::from("a"), JsonValue::Bool(true))
404 .is_none());
405 let old = object.insert(String::from("a"), JsonValue::Bool(false));
406 assert_eq!(old, Some(JsonValue::Bool(true)));
407 assert_eq!(object.len(), 1);
408 }
409
410 #[test]
411 fn deeply_nested_within_limits_does_not_overflow() {
412 let depth = 64;
414 let mut s = String::new();
415 for _ in 0..depth {
416 s.push('[');
417 }
418 s.push('1');
419 for _ in 0..depth {
420 s.push(']');
421 }
422 let _ = parse_str(&s); assert!(parse_with_limits(s.as_bytes(), JsonLimits::new().with_max_depth(64)).is_ok());
425 }
426
427 #[test]
428 fn arbitrary_bytes_never_panic() {
429 for input in [
431 &b""[..],
432 b" ",
433 b"{",
434 b"[",
435 b"\"",
436 b"\"\\",
437 b"\"\\u",
438 b"tru",
439 b"-",
440 b"[,]",
441 b"{,}",
442 b"\xff\xfe",
443 b"[[[",
444 b"}}}",
445 b"\"\\uD800\"",
446 b"1e",
447 b"{\"a\"}",
448 ] {
449 let _ = parse(input);
450 }
451 }
452
453 #[test]
454 fn json_test_suite_conformance() {
455 let must_accept: &[&[u8]] = &[
458 b"[]",
459 b"{}",
460 b"[1]",
461 b"[1,2,3]",
462 b"{\"a\":1}",
463 b"{\"a\":1,\"b\":2}",
464 b"[null,true,false]",
465 b"\"\\u0061\"",
466 b"\"\\uD834\\uDD1E\"", b"0",
468 b"-0",
469 b"123",
470 b"-123",
471 b"1.5",
472 b"1E10",
473 b"1e-10",
474 b"-1.2e+3",
475 b" 7 ",
476 b"\"abc\"",
477 b"true",
478 b"[[[[1]]]]",
479 b"{\"a\":{\"b\":[1,{\"c\":null}]}}",
480 ];
481 let must_reject: &[&[u8]] = &[
482 b"",
483 b"[1,]",
484 b"{\"a\":1,}",
485 b"[1 2]",
486 b"{\"a\" 1}",
487 b"{\"a\":1 \"b\":2}",
488 b"[1,,2]",
489 b"01",
490 b"1.",
491 b".1",
492 b"+1",
493 b"1e",
494 b"1e+",
495 b"0x1",
496 b"--1",
497 b"NaN",
498 b"Infinity",
499 b"[",
500 b"]",
501 b"{",
502 b"}",
503 b"\"",
504 b"\"\\x\"",
505 b"\"\\uZZZZ\"",
506 b"\"\x01\"", b"'single'",
508 b"1 1", b"tru",
510 b"nul",
511 b"\xEF\xBB\xBF1", b"\xff\xfe", b"\"\\uD800\"", b"/* comment */ 1",
515 b"{1:2}", ];
517 for input in must_accept {
518 assert!(parse(input).is_ok(), "should accept {input:?}");
519 }
520 for input in must_reject {
521 assert!(parse(input).is_err(), "should reject {input:?}");
522 }
523 }
524
525 #[test]
526 fn fuzz_parse_is_panic_free_and_roundtrips() {
527 let mut state: u64 = 0xD1B5_4A32_D192_ED03;
530 let mut next = || {
531 state ^= state << 13;
532 state ^= state >> 7;
533 state ^= state << 17;
534 state
535 };
536 let alphabet = b"{}[]\":,0123456789-+.eEtruefalsn \t\n\\/u";
538 let mut buf: Vec<u8> = Vec::new();
539 for _ in 0..40_000 {
540 buf.clear();
541 let len = (next() % 40) as usize;
542 for _ in 0..len {
543 let r = next();
544 let byte = if r & 7 == 0 {
545 (r >> 8) as u8 } else {
547 alphabet[((r >> 8) as usize) % alphabet.len()]
548 };
549 buf.push(byte);
550 }
551 if let Ok(value) = parse(&buf) {
552 let compact = to_compact_string(&value);
553 let reparsed = parse_str(&compact).expect("compact output must reparse");
554 assert_eq!(reparsed, value);
555 assert_eq!(to_compact_string(&reparsed), compact);
556
557 #[cfg(feature = "canonical")]
559 if let Ok(canonical) = to_canonical_string(&value) {
560 let again = parse_str(&canonical).expect("canonical output must reparse");
561 assert_eq!(to_canonical_string(&again).unwrap(), canonical);
562 }
563 }
564 }
565 }
566
567 #[test]
568 fn value_accessors_return_inner_or_none() {
569 let v = parse_ok(r#"{"b":true,"n":7,"s":"x","a":[1],"nil":null}"#);
570 let o = v.as_object().expect("object");
571 assert!(o.get("nil").unwrap().is_null());
572 assert_eq!(o.get("b").unwrap().as_bool(), Some(true));
573 assert_eq!(o.get("s").unwrap().as_str(), Some("x"));
574 assert_eq!(o.get("n").unwrap().as_number().unwrap().as_str(), "7");
575 assert_eq!(o.get("a").unwrap().as_array().unwrap().len(), 1);
576
577 let b = JsonValue::Bool(true);
579 assert!(!b.is_null());
580 assert_eq!(b.as_str(), None);
581 assert_eq!(b.as_number(), None);
582 assert_eq!(b.as_array(), None);
583 assert!(b.as_object().is_none());
584 assert_eq!(JsonValue::Null.as_bool(), None);
585 }
586
587 #[test]
588 fn object_insert_get_iter_and_len() {
589 let mut obj = JsonObject::new();
590 assert!(obj.is_empty());
591 assert_eq!(obj.len(), 0);
592 assert!(!obj.contains_key("k"));
593
594 assert_eq!(obj.insert("k".to_string(), JsonValue::Bool(false)), None);
595 assert!(obj.contains_key("k"));
596 assert_eq!(obj.len(), 1);
597
598 let old = obj.insert("k".to_string(), JsonValue::Bool(true));
600 assert_eq!(old, Some(JsonValue::Bool(false)));
601 assert_eq!(obj.len(), 1);
602 assert_eq!(obj.get("k"), Some(&JsonValue::Bool(true)));
603 assert_eq!(obj.get("missing"), None);
604
605 obj.insert("k2".to_string(), JsonValue::Null);
606 let members: Vec<&str> = obj.iter().map(|m| m.key()).collect();
607 assert_eq!(members, ["k", "k2"]);
608 assert_eq!(obj.iter().next().unwrap().value(), &JsonValue::Bool(true));
609
610 assert_eq!(JsonObject::default().len(), 0);
611 }
612
613 #[test]
614 fn number_conversions_cover_each_error() {
615 let int = JsonNumber::new("42").unwrap();
616 assert!(int.is_integer());
617 assert_eq!(int.to_i64(), Ok(42));
618 assert_eq!(int.to_u64(), Ok(42));
619 assert_eq!(int.to_f64(), Ok(42.0));
620
621 let neg = JsonNumber::new("-1").unwrap();
622 assert_eq!(neg.to_u64(), Err(JsonNumberError::OutOfRange));
623
624 let frac = JsonNumber::new("1.5").unwrap();
625 assert!(!frac.is_integer());
626 assert_eq!(frac.to_i64(), Err(JsonNumberError::NotAnInteger));
627 assert_eq!(frac.to_u64(), Err(JsonNumberError::NotAnInteger));
628 assert_eq!(frac.to_f64(), Ok(1.5));
629
630 let huge = JsonNumber::new("99999999999999999999").unwrap();
631 assert_eq!(huge.to_i64(), Err(JsonNumberError::OutOfRange));
632
633 let overflow = JsonNumber::new("1e400").unwrap();
634 assert_eq!(overflow.to_f64(), Err(JsonNumberError::NotFinite));
635
636 assert_eq!(JsonNumber::new("+1"), Err(JsonNumberError::InvalidNumber));
637 assert_eq!(JsonNumber::try_from_f64(2.5).unwrap().to_f64(), Ok(2.5));
638 assert_eq!(
639 JsonNumber::try_from_f64(f64::NAN),
640 Err(JsonNumberError::NotFinite)
641 );
642 assert_eq!(
643 JsonNumber::try_from_f64(f64::INFINITY),
644 Err(JsonNumberError::NotFinite)
645 );
646 }
647
648 #[test]
649 fn limits_profiles_and_builders() {
650 assert_eq!(JsonLimits::default(), JsonLimits::new());
651 assert!(JsonLimits::conservative().max_input_bytes < JsonLimits::new().max_input_bytes);
652 assert!(JsonLimits::permissive().max_input_bytes > JsonLimits::new().max_input_bytes);
653
654 let tuned = JsonLimits::new()
655 .with_max_depth(8)
656 .with_max_input_bytes(1024)
657 .with_max_string_bytes(16)
658 .with_max_total_nodes(32);
659 assert_eq!(tuned.max_depth, 8);
660 assert_eq!(tuned.max_input_bytes, 1024);
661 assert_eq!(tuned.max_string_bytes, 16);
662 assert_eq!(tuned.max_total_nodes, 32);
663 }
664
665 #[test]
666 fn error_display_covers_each_kind() {
667 let cases: &[(&str, &str)] = &[
669 ("", "unexpected end of input"),
670 ("@", "unexpected byte"),
671 ("\"a\\xb\"", "invalid escape sequence"),
672 ("\"\\uZZZZ\"", "invalid unicode escape"),
673 ("\"\\uD800\"", "unpaired UTF-16 surrogate"),
674 ("01", "invalid number"),
675 ("{\"a\":1,\"a\":2}", "duplicate object key"),
676 ("true false", "trailing data after JSON value"),
677 ];
678 for (input, expected) in cases {
679 let err = parse_str(input).unwrap_err();
680 assert!(
681 err.to_string().contains(expected),
682 "input {input:?} -> {err} (expected to contain {expected:?})"
683 );
684 }
685
686 let ctrl = parse(b"\"\x01\"").unwrap_err();
688 assert!(ctrl.to_string().contains("unescaped control character"));
689
690 let utf8 = parse(b"\xff").unwrap_err();
692 assert!(utf8.to_string().contains("invalid UTF-8"));
693 }
694
695 #[test]
696 fn error_accessors_and_limit_display_with_path() {
697 let limits = JsonLimits::new().with_max_depth(1);
698 let err = parse_with_limits(b"[[1]]", limits).unwrap_err();
699 assert_eq!(
700 err.kind(),
701 &JsonErrorKind::LimitExceeded(JsonLimitKind::Depth)
702 );
703 assert!(err.offset() >= 1);
704 assert_eq!(err.line(), 1);
705 assert!(err.column() >= 1);
706 let shown = err.to_string();
707 assert!(shown.contains("limit exceeded: nesting depth"));
708 assert!(shown.contains("path: $"));
709 assert_eq!(JsonLimitKind::Depth.as_str(), "nesting depth");
710 }
711
712 #[test]
713 fn path_display_formats_keys_and_indices() {
714 let path = JsonPath::from_segments(vec![
715 JsonPathSegment::Key("users".to_string()),
716 JsonPathSegment::Index(3),
717 JsonPathSegment::Key("email".to_string()),
718 ]);
719 assert_eq!(path.to_string(), "$.users[3].email");
720 assert_eq!(path.segments().len(), 3);
721 assert_eq!(JsonPath::default().to_string(), "$");
722 }
723
724 #[test]
725 fn number_error_display_is_distinct() {
726 assert_eq!(
727 JsonNumberError::OutOfRange.to_string(),
728 "number out of range for target type"
729 );
730 assert_eq!(
731 JsonNumberError::NotAnInteger.to_string(),
732 "number is not an integer"
733 );
734 assert_eq!(
735 JsonNumberError::NotFinite.to_string(),
736 "number is not finite"
737 );
738 assert_eq!(
739 JsonNumberError::InvalidNumber.to_string(),
740 "not a valid JSON number"
741 );
742 }
743
744 #[test]
745 fn writer_serializes_all_branches() {
746 let mut obj = JsonObject::new();
747 obj.insert("off".to_string(), JsonValue::Bool(false));
748 obj.insert(
749 "esc".to_string(),
750 JsonValue::String("\u{08}\u{0C}\n\r\t\u{1F}".to_string()),
752 );
753 obj.insert(
754 "arr".to_string(),
755 JsonValue::Array(vec![JsonValue::Null, JsonValue::Bool(true)]),
756 );
757 let value = JsonValue::Object(obj);
758
759 let s = to_compact_string(&value);
760 assert_eq!(parse_str(&s).unwrap(), value);
763 assert_eq!(to_compact_vec(&value), s.clone().into_bytes());
764 assert!(s.starts_with("{\"off\":false,"));
765 assert!(s.ends_with(",\"arr\":[null,true]}"));
766 }
767
768 #[cfg(feature = "std")]
769 #[test]
770 fn errors_implement_std_error() {
771 fn assert_error<E: std::error::Error>(_: &E) {}
772 let parse_err = parse_str("").unwrap_err();
773 assert_error(&parse_err);
774 let num_err = JsonNumber::new("1.5").unwrap().to_i64().unwrap_err();
775 assert_error(&num_err);
776 }
777}