use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct AgencyRecord {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agency_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub abbreviation: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub department: Option<Value>,
#[serde(flatten)]
pub extra: HashMap<String, Value>,
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn decode_minimal() {
let body = json!({
"agency_id": "97",
"name": "Department of Defense",
"abbreviation": "DOD",
"code": "9700"
});
let a: AgencyRecord = serde_json::from_value(body).expect("decode");
assert_eq!(a.name.as_deref(), Some("Department of Defense"));
assert_eq!(a.code.as_deref(), Some("9700"));
assert!(a.extra.is_empty());
}
#[test]
fn extra_captures_forward_compatible_fields() {
let body = json!({
"name": "Department of Defense",
"code": "9700",
"future_field": {"version": 2}
});
let a: AgencyRecord = serde_json::from_value(body).expect("decode");
assert!(a.extra.contains_key("future_field"));
assert_eq!(
a.extra.get("future_field").and_then(|v| v.get("version")),
Some(&json!(2))
);
}
#[test]
fn round_trip_emits_extras() {
let body = json!({
"name": "GSA",
"code": "4700",
"future": "x"
});
let a: AgencyRecord = serde_json::from_value(body.clone()).expect("decode");
let re = serde_json::to_value(&a).expect("re-encode");
assert_eq!(re.get("future"), Some(&json!("x")));
assert_eq!(re.get("name"), Some(&json!("GSA")));
}
}