1use serde::de::{self, Deserializer, IgnoredAny, Visitor};
8use serde::Deserialize;
9use std::fmt;
10use std::marker::PhantomData;
11
12pub fn opt_string<'de, D: Deserializer<'de>>(d: D) -> Result<Option<String>, D::Error> {
18 d.deserialize_any(OptVisitor(PhantomData::<String>))
19}
20
21pub fn opt_i64<'de, D: Deserializer<'de>>(d: D) -> Result<Option<i64>, D::Error> {
27 d.deserialize_any(OptVisitor(PhantomData::<i64>))
28}
29
30pub fn opt_f64<'de, D: Deserializer<'de>>(d: D) -> Result<Option<f64>, D::Error> {
36 d.deserialize_any(OptVisitor(PhantomData::<f64>))
37}
38
39pub fn opt_bool<'de, D: Deserializer<'de>>(d: D) -> Result<Option<bool>, D::Error> {
45 d.deserialize_any(OptVisitor(PhantomData::<bool>))
46}
47
48pub fn vec<'de, D: Deserializer<'de>, T: Deserialize<'de>>(d: D) -> Result<Vec<T>, D::Error> {
54 d.deserialize_any(VecVisitor(PhantomData))
55}
56
57pub fn opt_object<'de, D: Deserializer<'de>, T: Deserialize<'de>>(
63 d: D,
64) -> Result<Option<T>, D::Error> {
65 d.deserialize_any(ObjectVisitor(PhantomData))
66}
67
68trait Lenient: Sized {
70 const EXPECTING: &'static str;
71 fn from_str(v: &str) -> Option<Self>;
72 fn from_i64(v: i64) -> Option<Self>;
73 fn from_u64(v: u64) -> Option<Self>;
74 fn from_f64(v: f64) -> Option<Self>;
75 fn from_bool(v: bool) -> Option<Self>;
76}
77
78impl Lenient for String {
79 const EXPECTING: &'static str = "a string";
80 fn from_str(v: &str) -> Option<Self> {
81 Some(v.to_owned())
82 }
83 fn from_i64(v: i64) -> Option<Self> {
84 Some(v.to_string())
85 }
86 fn from_u64(v: u64) -> Option<Self> {
87 Some(v.to_string())
88 }
89 fn from_f64(v: f64) -> Option<Self> {
90 Some(v.to_string())
91 }
92 fn from_bool(v: bool) -> Option<Self> {
93 Some(v.to_string())
94 }
95}
96
97impl Lenient for i64 {
98 const EXPECTING: &'static str = "an integer";
99 fn from_str(v: &str) -> Option<Self> {
100 v.parse::<i64>()
101 .ok()
102 .or_else(|| v.parse::<f64>().ok().map(|f| f as i64))
103 }
104 fn from_i64(v: i64) -> Option<Self> {
105 Some(v)
106 }
107 fn from_u64(v: u64) -> Option<Self> {
108 i64::try_from(v).ok()
109 }
110 fn from_f64(v: f64) -> Option<Self> {
111 Some(v as i64)
112 }
113 fn from_bool(v: bool) -> Option<Self> {
114 Some(i64::from(v))
115 }
116}
117
118impl Lenient for f64 {
119 const EXPECTING: &'static str = "a number";
120 fn from_str(v: &str) -> Option<Self> {
121 v.parse().ok()
122 }
123 fn from_i64(v: i64) -> Option<Self> {
124 Some(v as f64)
125 }
126 fn from_u64(v: u64) -> Option<Self> {
127 Some(v as f64)
128 }
129 fn from_f64(v: f64) -> Option<Self> {
130 Some(v)
131 }
132 fn from_bool(v: bool) -> Option<Self> {
133 Some(if v { 1.0 } else { 0.0 })
134 }
135}
136
137impl Lenient for bool {
138 const EXPECTING: &'static str = "a boolean";
139 fn from_str(v: &str) -> Option<Self> {
140 match v {
141 "true" | "1" => Some(true),
142 "false" | "0" | "" => Some(false),
143 _ => None,
144 }
145 }
146 fn from_i64(v: i64) -> Option<Self> {
147 Some(v != 0)
148 }
149 fn from_u64(v: u64) -> Option<Self> {
150 Some(v != 0)
151 }
152 fn from_f64(v: f64) -> Option<Self> {
153 Some(v != 0.0)
154 }
155 fn from_bool(v: bool) -> Option<Self> {
156 Some(v)
157 }
158}
159
160struct OptVisitor<T>(PhantomData<T>);
161
162impl<'de, T: Lenient> Visitor<'de> for OptVisitor<T> {
163 type Value = Option<T>;
164
165 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 f.write_str(T::EXPECTING)
167 }
168 fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
169 Ok(T::from_str(v))
170 }
171 fn visit_i64<E: de::Error>(self, v: i64) -> Result<Self::Value, E> {
172 Ok(T::from_i64(v))
173 }
174 fn visit_u64<E: de::Error>(self, v: u64) -> Result<Self::Value, E> {
175 Ok(T::from_u64(v))
176 }
177 fn visit_f64<E: de::Error>(self, v: f64) -> Result<Self::Value, E> {
178 Ok(T::from_f64(v))
179 }
180 fn visit_bool<E: de::Error>(self, v: bool) -> Result<Self::Value, E> {
181 Ok(T::from_bool(v))
182 }
183 fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
184 Ok(None)
185 }
186 fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
188 while seq.next_element::<IgnoredAny>()?.is_some() {}
189 Ok(None)
190 }
191 fn visit_map<A: de::MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
192 while map.next_entry::<IgnoredAny, IgnoredAny>()?.is_some() {}
193 Ok(None)
194 }
195}
196
197macro_rules! skip_other_values {
199 ($empty:expr) => {
200 fn visit_str<E: de::Error>(self, _: &str) -> Result<Self::Value, E> {
201 Ok($empty)
202 }
203 fn visit_i64<E: de::Error>(self, _: i64) -> Result<Self::Value, E> {
204 Ok($empty)
205 }
206 fn visit_u64<E: de::Error>(self, _: u64) -> Result<Self::Value, E> {
207 Ok($empty)
208 }
209 fn visit_f64<E: de::Error>(self, _: f64) -> Result<Self::Value, E> {
210 Ok($empty)
211 }
212 fn visit_bool<E: de::Error>(self, _: bool) -> Result<Self::Value, E> {
213 Ok($empty)
214 }
215 fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
216 Ok($empty)
217 }
218 };
219}
220
221struct VecVisitor<T>(PhantomData<T>);
222
223impl<'de, T: Deserialize<'de>> Visitor<'de> for VecVisitor<T> {
224 type Value = Vec<T>;
225
226 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227 f.write_str("an array")
228 }
229 fn visit_seq<A: de::SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
230 Vec::deserialize(de::value::SeqAccessDeserializer::new(seq))
231 }
232 fn visit_map<A: de::MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
233 while map.next_entry::<IgnoredAny, IgnoredAny>()?.is_some() {}
234 Ok(Vec::new())
235 }
236 skip_other_values!(Vec::new());
237}
238
239struct ObjectVisitor<T>(PhantomData<T>);
240
241impl<'de, T: Deserialize<'de>> Visitor<'de> for ObjectVisitor<T> {
242 type Value = Option<T>;
243
244 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245 f.write_str("an object")
246 }
247 fn visit_map<A: de::MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> {
248 T::deserialize(de::value::MapAccessDeserializer::new(map)).map(Some)
249 }
250 fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
251 while seq.next_element::<IgnoredAny>()?.is_some() {}
252 Ok(None)
253 }
254 skip_other_values!(None);
255}
256
257#[cfg(test)]
258mod tests {
259 use super::*;
260 use serde_json::json;
261
262 #[derive(Debug, Deserialize, PartialEq)]
263 struct Row {
264 #[serde(default, deserialize_with = "opt_string")]
265 s: Option<String>,
266 #[serde(default, deserialize_with = "opt_i64")]
267 i: Option<i64>,
268 #[serde(default, deserialize_with = "opt_f64")]
269 f: Option<f64>,
270 #[serde(default, deserialize_with = "opt_bool")]
271 b: Option<bool>,
272 #[serde(default, deserialize_with = "vec")]
273 v: Vec<u8>,
274 }
275
276 fn row(v: serde_json::Value) -> Row {
277 serde_json::from_value(v).unwrap()
278 }
279
280 #[test]
281 fn strings_accept_scalars() {
282 assert_eq!(row(json!({"s": "x"})).s.as_deref(), Some("x"));
283 assert_eq!(row(json!({"s": -1})).s.as_deref(), Some("-1"));
284 assert_eq!(row(json!({"s": 1})).s.as_deref(), Some("1"));
285 assert_eq!(row(json!({"s": 1.5})).s.as_deref(), Some("1.5"));
286 assert_eq!(row(json!({"s": true})).s.as_deref(), Some("true"));
287 assert_eq!(row(json!({"s": null})).s, None);
288 assert_eq!(row(json!({})).s, None);
289 }
290
291 #[test]
292 fn integers_accept_strings_and_floats() {
293 assert_eq!(row(json!({"i": 5})).i, Some(5));
294 assert_eq!(row(json!({"i": -5})).i, Some(-5));
295 assert_eq!(row(json!({"i": "1616127454"})).i, Some(1616127454));
296 assert_eq!(row(json!({"i": "1.9"})).i, Some(1));
297 assert_eq!(row(json!({"i": "x"})).i, None);
298 assert_eq!(row(json!({"i": 2.7})).i, Some(2));
299 assert_eq!(row(json!({"i": u64::MAX})).i, None);
300 assert_eq!(row(json!({"i": true})).i, Some(1));
301 }
302
303 #[test]
304 fn floats_accept_strings_and_integers() {
305 assert_eq!(row(json!({"f": 0.5})).f, Some(0.5));
306 assert_eq!(row(json!({"f": "0.25"})).f, Some(0.25));
307 assert_eq!(row(json!({"f": -2})).f, Some(-2.0));
308 assert_eq!(row(json!({"f": 3})).f, Some(3.0));
309 assert_eq!(row(json!({"f": true})).f, Some(1.0));
310 assert_eq!(row(json!({"f": false})).f, Some(0.0));
311 }
312
313 #[test]
314 fn booleans_accept_numbers_and_strings() {
315 assert_eq!(row(json!({"b": true})).b, Some(true));
316 assert_eq!(row(json!({"b": "true"})).b, Some(true));
317 assert_eq!(row(json!({"b": "1"})).b, Some(true));
318 assert_eq!(row(json!({"b": "false"})).b, Some(false));
319 assert_eq!(row(json!({"b": "0"})).b, Some(false));
320 assert_eq!(row(json!({"b": ""})).b, Some(false));
321 assert_eq!(row(json!({"b": "maybe"})).b, None);
322 assert_eq!(row(json!({"b": 0})).b, Some(false));
323 assert_eq!(row(json!({"b": -1})).b, Some(true));
324 assert_eq!(row(json!({"b": 0.0})).b, Some(false));
325 }
326
327 #[test]
328 fn structured_values_in_scalar_fields_are_dropped() {
329 let r = row(json!({"s": [1, 2], "i": {"a": 1}, "v": [1]}));
330 assert_eq!(r.s, None);
331 assert_eq!(r.i, None);
332 assert_eq!(r.v, vec![1]);
333 }
334
335 #[test]
336 fn non_array_vec_becomes_empty() {
337 for v in [
338 json!(null),
339 json!("x"),
340 json!(-1),
341 json!(1),
342 json!(1.5),
343 json!(true),
344 json!({"a": 1}),
345 ] {
346 assert!(row(json!({ "v": v })).v.is_empty());
347 }
348 }
349
350 #[derive(Debug, Deserialize, PartialEq)]
351 struct Inner {
352 a: u8,
353 }
354
355 #[derive(Debug, Deserialize, PartialEq)]
356 struct Outer {
357 #[serde(default, deserialize_with = "opt_object")]
358 o: Option<Inner>,
359 }
360
361 #[test]
362 fn objects_accept_only_maps() {
363 let o = |v: serde_json::Value| {
364 serde_json::from_value::<Outer>(json!({ "o": v }))
365 .unwrap()
366 .o
367 };
368 assert_eq!(o(json!({"a": 1})), Some(Inner { a: 1 }));
369 for v in [
370 json!(null),
371 json!(""),
372 json!(-1),
373 json!(1),
374 json!(1.5),
375 json!(false),
376 json!([1, 2]),
377 ] {
378 assert_eq!(o(v), None);
379 }
380 assert!(serde_json::from_value::<Outer>(json!({"o": {"a": "x"}})).is_err());
381 }
382
383 #[test]
384 fn expecting_message_names_the_type() {
385 struct Probe<T>(PhantomData<T>);
387 impl<T: Lenient> fmt::Display for Probe<T> {
388 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
389 OptVisitor::<T>(PhantomData).expecting(f)
390 }
391 }
392 assert_eq!(Probe::<String>(PhantomData).to_string(), "a string");
393 assert_eq!(Probe::<i64>(PhantomData).to_string(), "an integer");
394 assert_eq!(Probe::<f64>(PhantomData).to_string(), "a number");
395 assert_eq!(Probe::<bool>(PhantomData).to_string(), "a boolean");
396 struct Expect<V>(V);
397 impl<'de, V: Visitor<'de>> fmt::Display for Expect<V> {
398 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
399 self.0.expecting(f)
400 }
401 }
402 assert_eq!(
403 Expect(VecVisitor::<u8>(PhantomData)).to_string(),
404 "an array"
405 );
406 assert_eq!(
407 Expect(ObjectVisitor::<u8>(PhantomData)).to_string(),
408 "an object"
409 );
410 }
411
412 #[test]
413 fn bytes_and_char_inputs_are_rejected_with_type_message() {
414 use serde::de::value::{BytesDeserializer, Error};
416 let err = opt_string(BytesDeserializer::<Error>::new(b"x")).unwrap_err();
417 assert!(err.to_string().contains("a string"));
418 }
419}