serde_single_key_map/
lib.rs1use std::fmt;
49use std::marker::PhantomData;
50
51use serde::de::{self, Deserializer, DeserializeOwned};
52
53pub fn deserialize<'de, V, D>(d: D) -> Result<V, D::Error>
54where
55 D: Deserializer<'de>,
56 V: DeserializeOwned,
57{
58 struct SingleKeyMapVisitor<V: DeserializeOwned>(PhantomData<V>);
59
60 impl<'de, V> de::Visitor<'de> for SingleKeyMapVisitor<V>
61 where
62 V: DeserializeOwned,
63 {
64 type Value = V;
65
66 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
67 formatter.write_str("a map")
68 }
69
70 #[inline]
71 fn visit_map<T>(self, mut visitor: T) -> Result<V, T::Error>
72 where
73 T: de::MapAccess<'de>,
74 {
75 let item: Option<(String, V)> = visitor.next_entry()?;
76 if let Some((_, value)) = item {
77 return Ok(value);
78 }
79 Err(de::Error::custom("No single key value in map"))
80 }
81 }
82 d.deserialize_map(SingleKeyMapVisitor(PhantomData))
83}
84
85#[cfg(test)]
86mod tests {
87 use serde::Deserialize;
88
89 #[derive(Debug, Deserialize)]
90 struct Project {
91 name: String,
92 #[serde(deserialize_with = "crate::deserialize")]
93 items: Vec<Item>,
94 }
95
96 #[derive(Debug, Deserialize)]
97 struct Item {
98 name: String,
99 source: String,
100 }
101
102 #[test]
103 fn test_deserialize() {
104 let s = r#"{
105 "name": "test",
106 "items": {
107 "item": [
108 {
109 "name": "name",
110 "source": "name.rs"
111 }
112 ]
113 }
114 }"#;
115 let project: Project = serde_json::from_str(s).expect("deserialize failed");
116 assert_eq!(project.name, "test");
117 assert_eq!(project.items.len(), 1);
118 let item = &project.items[0];
119 assert_eq!(item.name, "name");
120 assert_eq!(item.source, "name.rs");
121 }
122
123 #[test]
124 #[should_panic]
125 fn test_deserialize_with_multiple_keys() {
126 let s = r#"{
127 "name": "test",
128 "items": {
129 "item": [
130 {
131 "name": "name",
132 "source": "name.rs"
133 }
134 ],
135 "extra": "test"
136 }
137 }"#;
138 let _project: Project = serde_json::from_str(s).expect("deserialize failed");
139 }
140
141 #[test]
142 #[should_panic]
143 fn test_deserialize_with_empty_map() {
144 let s = r#"{
145 "name": "test",
146 "items": {}
147 }"#;
148 let _project: Project = serde_json::from_str(s).expect("deserialize failed");
149 }
150}