diff --git a/src/lib.rs b/src/lib.rs index 59ee84d..8a0331d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,10 +27,8 @@ fn parse_bool(input: &str) -> IResult<&str, JsonValue> { .map(JsonValue::Boolean) .parse(input) } -fn parse_string(input: &str) -> IResult<&str, JsonValue> { - delimited(tag("\""), parse_string_inner, tag("\"")) - .map(JsonValue::String) - .parse(input) +fn parse_string(input: &str) -> IResult<&str, String> { + delimited(tag("\""), parse_string_inner, tag("\"")).parse(input) } fn parse_string_inner(input: &str) -> IResult<&str, String> { let mut string_chunks = vec![]; @@ -74,9 +72,29 @@ fn parse_array(input: &str) -> IResult<&str, JsonValue> { .parse(input) } +fn parse_object(input: &str) -> IResult<&str, JsonValue> { + delimited(tag("{"), separated_list0(tag(","), parse_pair), tag("}")) + .map(|kvps| kvps.into_iter().collect::>()) + .map(JsonValue::Object) + .parse(input) +} + +fn parse_pair(input: &str) -> IResult<&str, (String, JsonValue)> { + (parse_string, tag(":"), deserialize_json) + .map(|(k, _, v)| (k, v)) + .parse(input) +} + pub fn deserialize_json(json: &str) -> IResult<&str, JsonValue> { // map_res(); - alt((parse_null, parse_bool, parse_string, parse_array)).parse(json) + alt(( + parse_null, + parse_bool, + parse_string.map(JsonValue::String), + parse_array, + parse_object, + )) + .parse(json) } #[cfg(test)] @@ -150,6 +168,32 @@ mod tests { ]) ); } + #[test] + fn deserializes_simple_objects() { + let t = deserialize_json("{}").unwrap(); + assert_eq!(t.1, JsonValue::Object(HashMap::new())); + let f = deserialize_json("{\"\":[]}").unwrap(); + assert_eq!( + f.1, + JsonValue::Object( + vec![(String::new(), JsonValue::Array(vec![]))] + .into_iter() + .collect() + ) + ); + } + + #[test] + fn deserializes_object() { + let result = deserialize_json(r#"{"includeLikes":true,"includeShares":true,"includeFollows":true,"includeReplies":true,"includeComments":true}"#).unwrap(); + let JsonValue::Object(hm) = result.1 else { + panic!() + }; + assert_eq!(hm.get("includeLikes"), Some(&JsonValue::Boolean(true))); + assert_eq!(hm.get("includeShares"), Some(&JsonValue::Boolean(true))); + assert_eq!(hm.get("includeFollows"), Some(&JsonValue::Boolean(true))); + assert_eq!(hm.get("includeReplies"), Some(&JsonValue::Boolean(true))); + } #[test] #[ignore]