use std::fmt;
use serde::de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor};
#[derive(Debug, Clone, PartialEq)]
pub enum JsonNode {
Null,
Bool(bool),
Number(String),
String(String),
Array(Vec<JsonNode>),
Object(Vec<(String, JsonNode)>),
}
struct JsonNodeVisitor;
impl<'de> Visitor<'de> for JsonNodeVisitor {
type Value = JsonNode;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("any valid JSON value")
}
fn visit_unit<E: de::Error>(self) -> Result<JsonNode, E> {
Ok(JsonNode::Null)
}
fn visit_none<E: de::Error>(self) -> Result<JsonNode, E> {
Ok(JsonNode::Null)
}
fn visit_bool<E: de::Error>(self, v: bool) -> Result<JsonNode, E> {
Ok(JsonNode::Bool(v))
}
fn visit_i64<E: de::Error>(self, v: i64) -> Result<JsonNode, E> {
Ok(JsonNode::Number(v.to_string()))
}
fn visit_u64<E: de::Error>(self, v: u64) -> Result<JsonNode, E> {
Ok(JsonNode::Number(v.to_string()))
}
fn visit_f64<E: de::Error>(self, v: f64) -> Result<JsonNode, E> {
Ok(JsonNode::Number(v.to_string()))
}
fn visit_str<E: de::Error>(self, v: &str) -> Result<JsonNode, E> {
Ok(JsonNode::String(v.to_string()))
}
fn visit_string<E: de::Error>(self, v: String) -> Result<JsonNode, E> {
Ok(JsonNode::String(v))
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<JsonNode, A::Error> {
let mut items = Vec::new();
while let Some(item) = seq.next_element()? {
items.push(item);
}
Ok(JsonNode::Array(items))
}
fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<JsonNode, A::Error> {
let mut entries = Vec::new();
while let Some((key, value)) = map.next_entry::<String, JsonNode>()? {
entries.push((key, value));
}
Ok(JsonNode::Object(entries))
}
}
impl<'de> Deserialize<'de> for JsonNode {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_any(JsonNodeVisitor)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn parse(s: &str) -> JsonNode {
serde_json::from_str(s).expect("valid JSON")
}
#[test]
fn duplicate_keys_are_all_preserved() {
let node = parse(r#"{"a":"first","a":"second"}"#);
let JsonNode::Object(entries) = node else {
panic!("expected object");
};
assert_eq!(
entries,
vec![
("a".to_string(), JsonNode::String("first".to_string())),
("a".to_string(), JsonNode::String("second".to_string())),
],
"both values must survive; keeping only one is a parser-differential evasion"
);
}
#[test]
fn object_order_is_preserved() {
let JsonNode::Object(entries) = parse(r#"{"z":1,"a":2}"#) else {
panic!("expected object");
};
let keys: Vec<&str> = entries.iter().map(|(k, _)| k.as_str()).collect();
assert_eq!(keys, vec!["z", "a"]);
}
#[test]
fn scalars_round_trip() {
assert_eq!(parse("null"), JsonNode::Null);
assert_eq!(parse("true"), JsonNode::Bool(true));
assert_eq!(parse(r#""s""#), JsonNode::String("s".to_string()));
assert_eq!(parse("42"), JsonNode::Number("42".to_string()));
}
#[test]
fn large_integers_keep_their_exact_value() {
assert_eq!(
parse("9007199254740993"),
JsonNode::Number("9007199254740993".to_string())
);
}
#[test]
fn nested_structures_parse() {
assert_eq!(
parse(r#"{"a":[1,{"b":null}]}"#),
JsonNode::Object(vec![(
"a".to_string(),
JsonNode::Array(vec![
JsonNode::Number("1".to_string()),
JsonNode::Object(vec![("b".to_string(), JsonNode::Null)]),
])
)])
);
}
}