Baseline: Serde through 1.0.209. Covers later Serde and serde_json changes represented by 1.0.220-serde-core, including serde_json releases through 1.0.150.
Reference index
| Reference | Topics |
|---|---|
| Core traits and dependencies | Choosing serde or serde_core; derive support; trait-path diagnostics |
| JSON compatibility and values | Version floors; enum object keys; arbitrary-precision numbers; Map parsing and deserialization; Value defaults; RawValue; deterministic key ordering |
Dependency and compatibility changes
Choose serde unless a trait-only dependency is intentional
serde_core 1.0.220 contains the core traits and supporting APIs:
SerializeDeserializeSerializerDeserializer- the supporting
seranddemodules
It deliberately does not provide #[derive(Serialize)] or
#[derive(Deserialize)].
Depend directly on serde_core only when a crate uses traits as bounds or
writes implementations by hand:
[dependencies]
serde_core = "1.0.220"
pub fn require_serializable<T: serde_core::Serialize>(_: &T) {}
Keep depending on serde when the crate derives either trait. serde
re-exports the same traits and remains the general-purpose default:
[dependencies]
serde = { version = "1.0.220", features = ["derive"] }
#[derive(serde::Serialize, serde::Deserialize)]
struct Record {
id: u64,
}
Read serde_core paths in errors as ordinary Serde traits
After the traits moved to serde_core, an unsatisfied bound from a format
crate can appear as:
T: serde_core::ser::Serialize
This does not normally call for a separate compatibility feature. Fix the
underlying Serde implementation by deriving serde::Serialize, enabling
serde's derive feature, or enabling the dependency's existing serde
feature.
Respect serde_json's Serde version floor
serde_json 1.0.145 requires Serde 1.0.220 or newer. If a dependency graph
pins Serde below 1.0.220, either update Serde or keep serde_json below
1.0.145.
Do not serialize non-string enum representations as object keys
As of serde_json 1.0.150, enum keys whose Serde representation is not a
string are rejected during JSON object serialization. Give data-carrying
variants an explicit string-key representation instead of relying on a
non-string enum representation.
Expect arbitrary-precision spelling changes
In serde_json 1.0.149, number strings emitted with the
arbitrary_precision feature were aligned with zmij formatting. Numeric
values remain equivalent, but their exact serialized spelling can change.
Review snapshots, hashes, signatures, golden files, and byte-for-byte tests
when upgrading.
Common serde_json value operations
Deserialize directly from an object map
Since serde_json 1.0.131, owned and borrowed object maps implement both
Serde Deserializer and IntoDeserializer:
use serde::Deserialize;
use serde_json::{Map, Value};
#[derive(Deserialize)]
struct Config {
enabled: bool,
}
let map: Map<String, Value> =
serde_json::from_str(r#"{"enabled":true}"#).unwrap();
let config = Config::deserialize(map).unwrap();
assert!(config.enabled);
There is no need to wrap the map in Value::Object or serialize it back to
text first. Use a borrowed &Map<String, Value> when the caller must retain
the map.
Parse an object map with FromStr
Since serde_json 1.0.143, Map<String, Value> supports .parse():
let object: serde_json::Map<String, serde_json::Value> =
r#"{"answer":42}"#.parse().unwrap();
assert_eq!(object["answer"], serde_json::json!(42));
Default a missing shared value to JSON null
Since serde_json 1.0.142, &Value implements Default. This makes a
missing optional shared reference default to a shared JSON null value:
let value = serde_json::json!({});
let missing: &serde_json::Value =
value.get("missing").unwrap_or_default();
assert!(missing.is_null());
This is useful for read-only fallback behavior. It does not insert a value into the source object.
Reuse static raw JSON literals
With the raw_value feature enabled, RawValue::NULL, RawValue::TRUE, and
RawValue::FALSE provide static raw fragments (since serde_json 1.0.134):
use serde_json::value::RawValue;
let raw: &'static RawValue = RawValue::NULL;
assert_eq!(raw.get(), "null");
Use these constants instead of allocating or parsing a boxed RawValue for
one of the three JSON literals.
Sort object keys deterministically
Since serde_json 1.0.129:
Map::sort_keys()sorts one object.Value::sort_all_objects()recursively sorts all objects in a tree.
let mut value = serde_json::json!({
"z": {"second": 2, "first": 1},
"a": 0,
});
value.sort_all_objects();
assert_eq!(
value.to_string(),
r#"{"a":0,"z":{"first":1,"second":2}}"#,
);
These methods matter when the preserve_order feature is enabled. Without
that feature, object maps are already maintained in sorted order and
sort_keys() does no work.
Upgrade checklist
- Keep
serdewithderiveenabled anywhere derives are used. - Use
serde_coredirectly only for intentionally trait-only crates. - Treat diagnostic paths through
serde_coreas the regular Serde traits. - Pair
serde_json1.0.145 or newer with Serde 1.0.220 or newer. - Convert enum object keys to explicit string representations.
- Recheck exact-number snapshots when
arbitrary_precisionis enabled. - Prefer direct
Mapdeserialization over JSON text round trips. - Sort objects before deterministic output when
preserve_orderis used.