#[cfg(feature = "raw_value")] use ref_cast::RefCast; use serde::de::{self, IgnoredAny, IntoDeserializer}; use serde::ser::{self, SerializeMap, SerializeSeq, Serializer}; use serde::{Deserialize, Serialize}; use serde_bytes::{ByteBuf, Bytes}; #[cfg(feature = "raw_value")] use serde_json::value::RawValue; use serde_json::{
from_reader, from_slice, from_str, from_value, json, to_string, to_string_pretty, to_value,
to_vec, Deserializer, Number, Value,
}; use std::collections::BTreeMap; #[cfg(feature = "raw_value")] use std::collections::HashMap; use std::fmt::{self, Debug}; use std::hash::BuildHasher; #[cfg(feature = "raw_value")] use std::hash::{Hash, Hasher}; use std::io; use std::iter; use std::marker::PhantomData; use std::mem; use std::str::FromStr; use std::{f32, f64};
fn test_encode_ok<T>(errors: &[(T, &str)]) where
T: PartialEq + Debug + ser::Serialize,
{ for &(ref value, out) in errors { let out = out.to_string();
let s = to_string(value).unwrap();
assert_eq!(s, out);
let v = to_value(value).unwrap(); let s = to_string(&v).unwrap();
assert_eq!(s, out);
}
}
fn test_pretty_encode_ok<T>(errors: &[(T, &str)]) where
T: PartialEq + Debug + ser::Serialize,
{ for &(ref value, out) in errors { let out = out.to_string();
let s = to_string_pretty(value).unwrap();
assert_eq!(s, out);
let v = to_value(value).unwrap(); let s = to_string_pretty(&v).unwrap();
assert_eq!(s, out);
}
}
fn test_parse_ok<T>(tests: Vec<(&str, T)>) where
T: Clone + Debug + PartialEq + ser::Serialize + de::DeserializeOwned,
{ for (s, value) in tests { let v: T = from_str(s).unwrap();
assert_eq!(v, value.clone());
let v: T = from_slice(s.as_bytes()).unwrap();
assert_eq!(v, value.clone());
// Make sure we can deserialize into a `Value`. let json_value: Value = from_str(s).unwrap();
assert_eq!(json_value, to_value(&value).unwrap());
// Make sure we can deserialize from a `&Value`. let v = T::deserialize(&json_value).unwrap();
assert_eq!(v, value);
// Make sure we can deserialize from a `Value`. let v: T = from_value(json_value.clone()).unwrap();
assert_eq!(v, value);
// Make sure we can round trip back to `Value`. let json_value2: Value = from_value(json_value.clone()).unwrap();
assert_eq!(json_value2, json_value);
// Make sure we can fully ignore. let twoline = s.to_owned() + "\n3735928559"; letmut de = Deserializer::from_str(&twoline);
IgnoredAny::deserialize(&mut de).unwrap();
assert_eq!(0xDEAD_BEEF, u64::deserialize(&mut de).unwrap());
// Make sure every prefix is an EOF error, except that a prefix of a // number may be a valid number. if !json_value.is_number() { for (i, _) in s.trim_end().char_indices() {
assert!(from_str::<Value>(&s[..i]).unwrap_err().is_eof());
assert!(from_str::<IgnoredAny>(&s[..i]).unwrap_err().is_eof());
}
}
}
}
// For testing representations that the deserializer accepts but the serializer // never generates. These do not survive a round-trip through Value. fn test_parse_unusual_ok<T>(tests: Vec<(&str, T)>) where
T: Clone + Debug + PartialEq + ser::Serialize + de::DeserializeOwned,
{ for (s, value) in tests { let v: T = from_str(s).unwrap();
assert_eq!(v, value.clone());
let v: T = from_slice(s.as_bytes()).unwrap();
assert_eq!(v, value.clone());
}
}
macro_rules! test_parse_err {
($name:ident::<$($ty:ty),*>($arg:expr) => $expected:expr) => { let actual = $name::<$($ty),*>($arg).unwrap_err().to_string();
assert_eq!(actual, $expected, "unexpected {} error", stringify!($name));
};
}
fn test_parse_err<T>(errors: &[(&str, &'static str)]) where
T: Debug + PartialEq + de::DeserializeOwned,
{ for &(s, err) in errors {
test_parse_err!(from_str::<T>(s) => err);
test_parse_err!(from_slice::<T>(s.as_bytes()) => err);
}
}
fn test_parse_slice_err<T>(errors: &[(&[u8], &'static str)]) where
T: Debug + PartialEq + de::DeserializeOwned,
{ for &(s, err) in errors {
test_parse_err!(from_slice::<T>(s) => err);
}
}
fn test_fromstr_parse_err<T>(errors: &[(&str, &'static str)]) where
T: Debug + PartialEq + FromStr,
<T as FromStr>::Err: ToString,
{ for &(s, err) in errors { let actual = s.parse::<T>().unwrap_err().to_string();
assert_eq!(actual, err, "unexpected parsing error");
}
}
#[test] fn test_parse_null() {
test_parse_err::<()>(&[
("n", "EOF while parsing a value at line 1 column 1"),
("nul", "EOF while parsing a value at line 1 column 3"),
("nulla", "trailing characters at line 1 column 5"),
]);
test_parse_ok(vec![("null", ())]);
}
#[test] fn test_parse_bool() {
test_parse_err::<bool>(&[
("t", "EOF while parsing a value at line 1 column 1"),
("truz", "expected ident at line 1 column 4"),
("f", "EOF while parsing a value at line 1 column 1"),
("faz", "expected ident at line 1 column 3"),
("truea", "trailing characters at line 1 column 5"),
("falsea", "trailing characters at line 1 column 6"),
]);
#[test] fn test_parse_char() {
test_parse_err::<char>(&[
( "\"ab\"", "invalid value: string \"ab\", expected a character at line 1 column 4",
),
( "10", "invalid type: integer `10`, expected a character at line 1 column 2",
),
]);
#[test] fn test_parse_number_errors() {
test_parse_err::<f64>(&[
("+", "expected value at line 1 column 1"),
(".", "expected value at line 1 column 1"),
("-", "EOF while parsing a value at line 1 column 1"),
("00", "invalid number at line 1 column 2"),
("0x80", "trailing characters at line 1 column 2"),
("\\0", "expected value at line 1 column 1"),
(".0", "expected value at line 1 column 1"),
("0.", "EOF while parsing a value at line 1 column 2"),
("1.", "EOF while parsing a value at line 1 column 2"),
("1.a", "invalid number at line 1 column 3"),
("1.e1", "invalid number at line 1 column 3"),
("1e", "EOF while parsing a value at line 1 column 2"),
("1e+", "EOF while parsing a value at line 1 column 3"),
("1a", "trailing characters at line 1 column 2"),
( "100e777777777777777777777777777", "number out of range at line 1 column 14",
),
( "-100e777777777777777777777777777", "number out of range at line 1 column 15",
),
( "1000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\ 000000000", // 1e309 "number out of range at line 1 column 310",
),
( "1000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\
.0e9", // 1e309 "number out of range at line 1 column 305",
),
( "1000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000\
e9", // 1e309 "number out of range at line 1 column 303",
),
]);
}
// Test roundtrip with some values that were not perfectly roundtripped by the // old f64 deserializer. #[cfg(feature = "float_roundtrip")] #[test] fn test_roundtrip_f64() { for &float in &[ // Samples from quickcheck-ing roundtrip with `input: f64`. Comments // indicate the value returned by the old deserializer. 51.24817837550540_4, // 51.2481783755054_1
-93.3113703768803_3, // -93.3113703768803_2
-36.5739948427534_36, // -36.5739948427534_4 52.31400820410624_4, // 52.31400820410624_ 97.4536532003468_5, // 97.4536532003468_4 // Samples from `rng.next_u64` + `f64::from_bits` + `is_finite` filter. 2.0030397744267762e-253, 7.101215824554616e260, 1.769268377902049e74,
-1.6727517818542075e58, 3.9287532173373315e299,
] { let json = serde_json::to_string(&float).unwrap(); let output: f64 = serde_json::from_str(&json).unwrap();
assert_eq!(float, output);
}
}
#[test] fn test_roundtrip_f32() { // This number has 1 ULP error if parsed via f64 and converted to f32. // https://github.com/serde-rs/json/pull/671#issuecomment-628534468 let float = 7.038531e-26; let json = serde_json::to_string(&float).unwrap(); let output: f32 = serde_json::from_str(&json).unwrap();
assert_eq!(float, output);
}
test_fromstr_parse_err::<Number>(&[
(" 1.0", "invalid number at line 1 column 1"),
("1.0 ", "invalid number at line 1 column 4"),
("\t1.0", "invalid number at line 1 column 1"),
("1.0\t", "invalid number at line 1 column 4"),
]);
#[test] fn test_parse_string() {
test_parse_err::<String>(&[
("\"", "EOF while parsing a string at line 1 column 1"),
("\"lol", "EOF while parsing a string at line 1 column 4"),
("\"lol\"a", "trailing characters at line 1 column 6"),
( "\"\\uD83C\\uFFFF\"", "lone leading surrogate in hex escape at line 1 column 13",
),
( "\"\n\"", "control character (\\u0000-\\u001F) found while parsing a string at line 2 column 0",
),
( "\"\x1F\"", "control character (\\u0000-\\u001F) found while parsing a string at line 1 column 2",
),
]);
test_parse_slice_err::<String>(&[
(
&[b'"', 159, 146, 150, b'"'], "invalid unicode code point at line 1 column 5",
),
(
&[b'"', b'\\', b'n', 159, 146, 150, b'"'], "invalid unicode code point at line 1 column 7",
),
(
&[b'"', b'\\', b'u', 48, 48, 51], "EOF while parsing a string at line 1 column 6",
),
(
&[b'"', b'\\', b'u', 250, 48, 51, 48, b'"'], "invalid escape at line 1 column 4",
),
(
&[b'"', b'\\', b'u', 48, 250, 51, 48, b'"'], "invalid escape at line 1 column 5",
),
(
&[b'"', b'\\', b'u', 48, 48, 250, 48, b'"'], "invalid escape at line 1 column 6",
),
(
&[b'"', b'\\', b'u', 48, 48, 51, 250, b'"'], "invalid escape at line 1 column 7",
),
(
&[b'"', b'\n', b'"'], "control character (\\u0000-\\u001F) found while parsing a string at line 2 column 0",
),
(
&[b'"', b'\x1F', b'"'], "control character (\\u0000-\\u001F) found while parsing a string at line 1 column 2",
),
]);
#[test] fn test_parse_list() {
test_parse_err::<Vec<f64>>(&[
("[", "EOF while parsing a list at line 1 column 1"),
("[ ", "EOF while parsing a list at line 1 column 2"),
("[1", "EOF while parsing a list at line 1 column 2"),
("[1,", "EOF while parsing a value at line 1 column 3"),
("[1,]", "trailing comma at line 1 column 4"),
("[1 2]", "expected `,` or `]` at line 1 column 4"),
("[]a", "trailing characters at line 1 column 3"),
]);
#[test] fn test_parse_object() {
test_parse_err::<BTreeMap<String, u32>>(&[
("{", "EOF while parsing an object at line 1 column 1"),
("{ ", "EOF while parsing an object at line 1 column 2"),
("{1", "key must be a string at line 1 column 2"),
("{ \"a\"", "EOF while parsing an object at line 1 column 5"),
("{\"a\"", "EOF while parsing an object at line 1 column 4"),
("{\"a\" ", "EOF while parsing an object at line 1 column 5"),
("{\"a\" 1", "expected `:` at line 1 column 6"),
("{\"a\":", "EOF while parsing a value at line 1 column 5"),
("{\"a\":1", "EOF while parsing an object at line 1 column 6"),
("{\"a\":1 1", "expected `,` or `}` at line 1 column 8"),
("{\"a\":1,", "EOF while parsing a value at line 1 column 7"),
("{}a", "trailing characters at line 1 column 3"),
]);
#[test] fn test_parse_enum_errors() {
test_parse_err::<Animal>(
&[
("{}", "expected value at line 1 column 2"),
("[]", "expected value at line 1 column 1"),
("\"unknown\"", "unknown variant `unknown`, expected one of `Dog`, `Frog`, `Cat`, `AntHive` at line 1 column 9"),
("{\"unknown\":null}", "unknown variant `unknown`, expected one of `Dog`, `Frog`, `Cat`, `AntHive` at line 1 column 10"),
("{\"Dog\":", "EOF while parsing a value at line 1 column 7"),
("{\"Dog\":}", "expected value at line 1 column 8"),
("{\"Dog\":{}}", "invalid type: map, expected unit at line 1 column 7"),
("\"Frog\"", "invalid type: unit variant, expected tuple variant"),
("\"Frog\" 0 ", "invalid type: unit variant, expected tuple variant"),
("{\"Frog\":{}}", "invalid type: map, expected tuple variant Animal::Frog at line 1 column 8"),
("{\"Cat\":[]}", "invalid length 0, expected struct variant Animal::Cat with 2 elements at line 1 column 9"),
("{\"Cat\":[0]}", "invalid length 1, expected struct variant Animal::Cat with 2 elements at line 1 column 10"),
("{\"Cat\":[0, \"\", 2]}", "trailing characters at line 1 column 16"),
("{\"Cat\":{\"age\": 5, \"name\": \"Kate\", \"foo\":\"bar\"}", "unknown field `foo`, expected `age` or `name` at line 1 column 39"),
// JSON does not allow trailing commas in data structures
("{\"Cat\":[0, \"Kate\",]}", "trailing comma at line 1 column 19"),
("{\"Cat\":{\"age\": 2, \"name\": \"Kate\",}}", "trailing comma at line 1 column 34"),
],
);
}
#[test] fn test_byte_buf_de_multiple() { let s: Vec<ByteBuf> = from_str(r#"["ab\nc", "cd\ne"]"#).unwrap(); let a = ByteBuf::from(b"ab\nc".to_vec()); let b = ByteBuf::from(b"cd\ne".to_vec());
assert_eq!(vec![a, b], s);
}
// Example of ownership stealing
assert_eq!(
data.pointer_mut("/a~1b")
.map(|m| mem::replace(m, json!(null)))
.unwrap(), 1
);
assert_eq!(data.pointer("/a~1b").unwrap(), &json!(null));
// Need to compare against a clone so we don't anger the borrow checker // by taking out two references to a mutable value letmut d2 = data.clone();
assert_eq!(data.pointer_mut("").unwrap(), &mut d2);
}
#[test] fn test_stack_overflow() { let brackets: String = iter::repeat('[')
.take(127)
.chain(iter::repeat(']').take(127))
.collect(); let _: Value = from_str(&brackets).unwrap();
let brackets = "[".repeat(129);
test_parse_err::<Value>(&[(&brackets, "recursion limit exceeded at line 1 column 128")]);
}
#[test] fn test_integer_key() { // map with integer keys let map = treemap!( 1 => 2,
-1 => 6,
); let j = r#"{"-1":6,"1":2}"#;
test_encode_ok(&[(&map, j)]);
test_parse_ok(vec![(j, map)]);
test_parse_err::<BTreeMap<i32, ()>>(&[
(
r#"{"x":null}"#, "invalid value: expected key to be a number in quotes at line 1 column 2",
),
(
r#"{" 123":null}"#, "invalid value: expected key to be a number in quotes at line 1 column 2",
),
(r#"{"123 ":null}"#, "expected `\"` at line 1 column 6"),
]);
let err = from_value::<BTreeMap<i32, ()>>(json!({" 123":null})).unwrap_err();
assert_eq!(
err.to_string(), "invalid value: expected key to be a number in quotes",
);
let err = from_value::<BTreeMap<i32, ()>>(json!({"123 ":null})).unwrap_err();
assert_eq!(
err.to_string(), "invalid value: expected key to be a number in quotes",
);
}
let j = r#"{"x": null}"#;
test_parse_err::<BTreeMap<Float, ()>>(&[(
j, "invalid value: expected key to be a number in quotes at line 1 column 2",
)]);
}
#[test] fn test_deny_non_finite_f32_key() { // We store float bits so that we can derive Ord, and other traits. In a // real context the code might involve a crate like ordered-float.
let map = treemap!(F32Bits(f32::INFINITY.to_bits()) => "x".to_owned());
assert!(serde_json::to_string(&map).is_err());
assert!(serde_json::to_value(map).is_err());
let map = treemap!(F32Bits(f32::NEG_INFINITY.to_bits()) => "x".to_owned());
assert!(serde_json::to_string(&map).is_err());
assert!(serde_json::to_value(map).is_err());
let map = treemap!(F32Bits(f32::NAN.to_bits()) => "x".to_owned());
assert!(serde_json::to_string(&map).is_err());
assert!(serde_json::to_value(map).is_err());
}
#[test] fn test_deny_non_finite_f64_key() { // We store float bits so that we can derive Ord, and other traits. In a // real context the code might involve a crate like ordered-float.
#[test] fn test_json_macro() { // This is tricky because the <...> is not a single TT and the comma inside // looks like an array element separator. let _ = json!([
<Result<(), ()> as Clone>::clone(&Ok(())),
<Result<(), ()> as Clone>::clone(&Err(()))
]);
// Same thing but in the map values. let _ = json!({ "ok": <Result<(), ()> as Clone>::clone(&Ok(())), "err": <Result<(), ()> as Clone>::clone(&Err(()))
});
// It works in map keys but only if they are parenthesized. let _ = json!({
(<Result<&str, ()> as Clone>::clone(&Ok("")).unwrap()): "ok",
(<Result<(), &str> as Clone>::clone(&Err("")).unwrap_err()): "err"
});
#[deny(unused_results)] let _ = json!({ "architecture": [true, null] });
}
let s: &str = from_slice(b"\"borrowed\"").unwrap();
assert_eq!("borrowed", s);
}
#[test] fn null_invalid_type() { let err = serde_json::from_str::<String>("null").unwrap_err();
assert_eq!(
format!("{}", err),
String::from("invalid type: null, expected a string at line 1 column 4")
);
}
#[test] fn test_integer128() { let signed = &[i128::MIN, -1, 0, 1, i128::MAX]; let unsigned = &[0, 1, u128::MAX];
for integer128 in signed { let expected = integer128.to_string();
assert_eq!(to_string(integer128).unwrap(), expected);
assert_eq!(from_str::<i128>(&expected).unwrap(), *integer128);
}
for integer128 in unsigned { let expected = integer128.to_string();
assert_eq!(to_string(integer128).unwrap(), expected);
assert_eq!(from_str::<u128>(&expected).unwrap(), *integer128);
}
test_parse_err::<i128>(&[
( "-170141183460469231731687303715884105729", "number out of range at line 1 column 40",
),
( "170141183460469231731687303715884105728", "number out of range at line 1 column 39",
),
]);
test_parse_err::<u128>(&[
("-1", "number out of range at line 1 column 1"),
( "340282366920938463463374607431768211456", "number out of range at line 1 column 39",
),
]);
}
#[test] fn test_integer128_to_value() { let signed = &[i128::from(i64::MIN), i128::from(u64::MAX)]; let unsigned = &[0, u128::from(u64::MAX)];
for integer128 in signed { let expected = integer128.to_string();
assert_eq!(to_value(integer128).unwrap().to_string(), expected);
}
for integer128 in unsigned { let expected = integer128.to_string();
assert_eq!(to_value(integer128).unwrap().to_string(), expected);
}
if !cfg!(feature = "arbitrary_precision") { let err = to_value(u128::from(u64::MAX) + 1).unwrap_err();
assert_eq!(err.to_string(), "number out of range");
}
}
let array_to_string = serde_json::to_string(&array_from_str).unwrap();
assert_eq!(r#"["a",42,{"foo": "bar"},null]"#, array_to_string);
}
#[cfg(feature = "raw_value")] #[test] fn test_raw_invalid_utf8() { let j = &[b'"', b'\xCE', b'\xF8', b'"']; let value_err = serde_json::from_slice::<Value>(j).unwrap_err(); let raw_value_err = serde_json::from_slice::<Box<RawValue>>(j).unwrap_err();
assert_eq!(
value_err.to_string(), "invalid unicode code point at line 1 column 4",
);
assert_eq!(
raw_value_err.to_string(), "invalid unicode code point at line 1 column 4",
);
}
impl<'de> Deserialize<'de> for MyMapKey { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where
D: de::Deserializer<'de>,
{ let s = <&str>::deserialize(deserializer)?; let n = s.parse().map_err(de::Error::custom)?;
Ok(MyMapKey(n))
}
}
let value = json!({ "map": { "1": null } });
Outer::deserialize(&value).unwrap();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.