The data structures are different but not incompatible… Let me explain.
These data structures are designed to be able to represent any syntactically valid data in their corresponding format. A serde_json::Value can represent any valid JSON document. A serde_yaml::Value can represent any valid YAML document. A serde_value::Value can represent any data that comes out of a Serde deserializer.
These are different because the different formats have different features and limitations. Some notable differences:
- TOML has a first-class datetime type that the other formats do not.
- JSON maps always have string keys while YAML map keys can be numbers, lists, maps etc.
- Serde differentiates between u8, u16, u32 etc while JSON, YAML, TOML do not.
Because of these differences, the different Value types are not interchangeable. I cannot use a serde_json::Value to represent an arbitrary YAML document because the YAML document may contain non-string map keys.
But still they are all compatible with each other! From Serde’s perspective, all of these Value types are just types that implement the Serialize and Deserialize traits. In that sense there is no difference between
#[derive(Serialize, Deserialize)] struct MyStruct. They are just types that implement Serialize and Deserialize. This is an important point so let me know if I have not explained it successfully.
So since they are just types that implement Serialize and Deserialize, we can take data in any format and deserialize it to a Value of any format. For example we can do:
let v: serde_json::Value = serde_yaml::from_str(...)?;
Of course if your YAML input contains a non-string map key then the deserialization will fail, but it shows that these Value types are maximally compatible across all formats.
So basically - pick whichever one can represent all the data that you care about. If you only care about JSON-like data (so string keys in maps, no explicit datetime type, etc) then use serde_json::Value everywhere. If you want maximum generality across all Serde data formats, use serde_value::Value.
I was wondering if it would make sense to unify them in a single external crate that covers all the cases and can be used by the specific format parsers.
(a) Given that all of these Value types are compatible with all the formats, I don’t think “covering all the cases” in one type is particularly valuable. People will use whichever type covers all the cases they care about, and a type that covers more cases than they care about is unwieldy.
(b) The specific format parsers don’t use these Value types anyway. Deserializing a JSON document into a data structure does not involve serde_json::Value at all. Data is deserialized directly from JSON bytes into the resulting data structure without ever going through serde_json::Value.
© The formats would not want to use a standard Value type even if there were such a thing. If I need to deserialize an unknown JSON blob and do basic manipulations on it, I would not want to use an “all the cases” type like serde_value::Value because I know that JSON does not differentiate between various bit-width numbers, so dealing with those would complicate my code unnecessarily.