Skip to main content

fuzzy_from_json_value/
fuzzy_from_json_value.rs

1// ---------------- [ File: fuzzy-from-json-value/src/fuzzy_from_json_value.rs ]
2crate::ix!();
3
4pub trait FuzzyFromJsonValue: Sized {
5    fn fuzzy_from_json_value(value: &serde_json::Value) -> Result<Self,FuzzyFromJsonValueError>;
6}
7
8error_tree!{
9
10    pub enum FuzzyFromJsonValueError {
11
12        Serde(::serde_path_to_error::Error<::serde_json::Error>),
13        SerdeJson(::serde_json::Error),
14
15        #[display("Expected an object for {target_type}, got {actual:?}")]
16        NotAnObject {
17            target_type: &'static str,
18            actual:      serde_json::Value,
19        },
20
21        #[display("MissingField: {field_name} for target={target_type}")]
22        MissingField {
23            field_name: &'static str,
24            target_type: &'static str,
25        },
26
27        #[display("Could not deserialize {target_type}: {source}")]
28        SerdeError {
29            target_type: &'static str,
30            source: serde_json::Error,
31        },
32
33        #[display("Other fuzzy error parsing {target_type}: {detail}")]
34        Other {
35            target_type: &'static str,
36            detail:      String,
37        },
38    }
39}
40
41use serde_path_to_error::{self, Error as PathError};
42
43/// Parse `value` into `T` and if there's a structure mismatch,
44/// you get an error message that includes a *JSON pointer path*
45/// to where the mismatch occurred.
46pub fn from_value_pathaware<T>(value: &serde_json::Value) -> Result<T, serde_json::Error>
47where
48    T: serde::de::DeserializeOwned,
49{
50    let value_str = value.to_string();
51
52    // (B) Turn that Value into a normal serde_json::Deserializer
53    let deser = &mut ::serde_json::Deserializer::from_str(&value_str);
54
55    let result: Result<T, _> = serde_path_to_error::deserialize(deser);
56
57    // (C) Pass the deserializer to serde_path_to_error
58    match result {
59        Ok(cfg) => Ok(cfg),
60        Err(path_err) => {
61            let path_string = path_err.path().to_string();
62            let underlying  = path_err.into_inner(); // the actual serde_json::Error
63            warn!(
64                "Fuzzy parse failed at path '{}': {}",
65                path_string,
66                underlying
67            );
68            Err(underlying)
69        }
70    }
71}