use std::collections::BTreeMap;
use rskit_errors::{AppError, AppResult};
use serde::de::DeserializeOwned;
pub type RawValue = serde_json::Value;
pub type RawTable = BTreeMap<String, RawValue>;
pub fn deserialize_subtree<T>(field: &str, value: RawValue) -> AppResult<T>
where
T: DeserializeOwned,
{
T::deserialize(value).map_err(|error| {
AppError::invalid_input(field, format!("invalid '{field}' configuration: {error}"))
})
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
#[derive(Debug, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
struct Sub {
enabled: bool,
retries: u16,
}
#[test]
fn deserialize_subtree_parses_typed_value() {
let value: RawValue = serde_json::json!({ "enabled": true, "retries": 3 });
let sub: Sub = deserialize_subtree("driver", value).unwrap();
assert_eq!(
sub,
Sub {
enabled: true,
retries: 3
}
);
}
#[test]
fn deserialize_subtree_rejects_unknown_field_with_named_error() {
let value: RawValue = serde_json::json!({ "enabled": true, "retries": 3, "extra": 1 });
let err = deserialize_subtree::<Sub>("driver", value).unwrap_err();
assert!(err.to_string().contains("driver"));
assert!(err.to_string().contains("unknown field"));
}
}