pub struct MapSkipError<K, V, I = ()>(/* private fields */);Expand description
Deserialize a map, skipping keys and values which fail to deserialize.
By default serde terminates if it fails to deserialize a key or a value when deserializing a map. Sometimes a map has heterogeneous keys or values but we only care about some specific types, and it is desirable to skip entries on errors.
You can be notified of skipped elements by providing a type that implements the InspectError trait.
The third generic argument I defaults to (), which does nothing.
It is especially useful in conjunction to #[serde(flatten)] to capture a map mixed in with
other entries which we don’t want to exhaust in the type definition.
The serialization behavior is identical to the underlying map.
The implementation supports both the HashMap and the BTreeMap from the standard library.
§Examples
§Basic Usage
#[serde_as]
#[derive(Deserialize, Serialize)]
struct VersionNames {
yanked: Vec<u16>,
#[serde_as(as = "MapSkipError<DisplayFromStr, _>")]
#[serde(flatten)]
names: BTreeMap<u16, String>,
}
let data = VersionNames {
yanked: vec![2, 5],
names: BTreeMap::from_iter([
(0u16, "v0".to_string()),
(1, "v1".to_string()),
(4, "v4".to_string())
]),
};
let source_json = r#"{
"0": "v0",
"1": "v1",
"4": "v4",
"yanked": [2, 5],
"last_updated": 1704085200
}"#;
let data_json = r#"{"yanked":[2,5],"0":"v0","1":"v1","4":"v4"}"#;
// Ensure serialization and deserialization produce the expected results
assert_eq!(data_json, serde_json::to_string(&data).unwrap());
assert_eq!(data, serde_json::from_str(source_json).unwrap());§Using InspectError to log skipped elements
struct ErrorInspector;
thread_local! {
static ERRORS: RefCell<Vec<String>> = RefCell::new(Vec::new());
}
impl InspectError for ErrorInspector {
fn inspect_error(error: impl serde::de::Error) {
ERRORS.with(|errors| errors.borrow_mut().push(error.to_string()));
}
}
#[serde_as]
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct S {
tag: String,
#[serde_as(as = "MapSkipError<_, _, ErrorInspector>")]
values: BTreeMap<String, u8>,
}
let json = r#"{"tag":"type","values":{"valid":42,"invalid": null,"another":"str","nested":[1,2,3]}}"#;
let s: S = serde_json::from_str(json).unwrap();
assert_eq!(s.values.len(), 1);
assert_eq!(s.values.get("valid"), Some(&42));
let errors = ERRORS.with(|errors| errors.borrow().clone());
assert_eq!(errors.len(), 3);
eprintln!("Errors: {errors:#?}");
assert!(errors[0].contains("invalid type: null, expected u8"));
assert!(errors[1].contains("invalid type: string \"str\", expected u8"));
assert!(errors[2].contains("invalid type: sequence, expected u8"));