json_ext/
object.rs

1use serde::{de, ser};
2use serde_json::value::RawValue;
3
4/// Represents a custom JSON object.
5#[derive(Debug, Clone)]
6pub struct Object<'a>(&'a RawValue);
7
8impl<'a> Object<'a> {
9    /// Convert a `&RawValue` to a `Object` object.
10    pub fn try_from<'b>(raw: &'b RawValue) -> serde_json::Result<Self>
11    where
12        'b: 'a,
13    {
14        check_raw(raw).map(Self).map_err(ser::Error::custom)
15    }
16
17    /// Converts to a specified type.
18    pub fn try_into<'b, T>(&'a self) -> serde_json::Result<T>
19    where
20        T: serde::Deserialize<'b>,
21        'a: 'b,
22    {
23        serde_json::from_str(self.0.get())
24    }
25}
26
27// TODO: whether implement default or not?
28// impl<'a> Default for Object<'a> {
29//     fn default() -> Self {
30//         //Self(unsafe { std::mem::transmute::<&str, &RawValue>("null") })
31//         serde_json::from_str::<Self>("null").unwrap()
32//     }
33// }
34
35impl<'a> PartialEq for Object<'a> {
36    fn eq(&self, other: &Self) -> bool {
37        self.0.get() == other.0.get()
38    }
39}
40
41impl<'a> ser::Serialize for Object<'a> {
42    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
43    where
44        S: serde::Serializer,
45    {
46        self.0.serialize(serializer)
47    }
48}
49
50impl<'de: 'a, 'a> de::Deserialize<'de> for Object<'a> {
51    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
52    where
53        D: serde::Deserializer<'de>,
54    {
55        let raw: &'a RawValue = de::Deserialize::deserialize(deserializer)?;
56        check_raw(raw).map(Self).map_err(de::Error::custom)
57    }
58}
59
60fn check_raw(raw: &RawValue) -> Result<&RawValue, &'static str> {
61    match raw.get().as_bytes().get(0) {
62        Some(b'{') | Some(b'n') => Ok(raw),
63        _ => Err("invalid value: expected null or object"),
64    }
65}
66
67#[cfg(test)]
68mod test {
69    use serde::{Deserialize, Serialize};
70    use serde_json::{from_str, value::to_raw_value, Map, Value};
71
72    use super::*;
73
74    #[derive(Serialize, Deserialize, Debug, PartialEq)]
75    struct Obj<'a> {
76        #[serde(borrow)]
77        ext: Object<'a>,
78    }
79
80    #[derive(Serialize, Deserialize, Debug, PartialEq)]
81    struct Ext<'a> {
82        f1: &'a str,
83        f2: i32,
84    }
85
86    #[test]
87    fn try_from_and_try_into() -> serde_json::Result<()> {
88        let object = Value::Object({
89            let mut m = Map::new();
90            m.insert("f1".into(), Value::String("abc".into()));
91            m.insert("f2".into(), Value::Number(123.into()));
92            m
93        });
94        let raw = to_raw_value(&object)?;
95
96        let obj = Object::try_from(raw.as_ref())?;
97        assert_eq!(
98            obj,
99            Object(serde_json::from_str(r#"{"f1":"abc","f2":123}"#)?)
100        );
101
102        let obj2 = obj.try_into::<Ext>()?;
103        assert_eq!(obj2, Ext { f1: "abc", f2: 123 });
104
105        Ok(())
106    }
107
108    #[test]
109    fn json() -> serde_json::Result<()> {
110        assert!(from_str::<Obj>(r#"{"ext":null}"#).is_ok());
111        assert!(from_str::<Obj>(r#"{"ext":true}"#).is_err());
112        assert!(from_str::<Obj>(r#"{"ext":1}"#).is_err());
113        assert!(from_str::<Obj>(r#"{"ext":"1"}"#).is_err());
114        assert!(from_str::<Obj>(r#"{"ext":[1]}"#).is_err());
115        assert!(from_str::<Obj>(r#"{"ext":{}}"#).is_ok());
116
117        let s1 = r#"{"ext": 	
118null}"#;
119        let o1 = from_str::<Obj>(s1)?;
120        assert_eq!(
121            o1,
122            Obj {
123                ext: Object::try_from(to_raw_value(&Value::Null)?.as_ref())?,
124            }
125        );
126        assert_eq!(serde_json::to_string(&o1)?, r#"{"ext":null}"#);
127
128        let s2 = r#"{"ext": 	
129{}
130 	}"#;
131        let o2 = serde_json::from_str::<Obj>(s2)?;
132        assert_eq!(
133            o2,
134            Obj {
135                ext: Object::try_from(to_raw_value(&Value::Object(Default::default()))?.as_ref())?,
136            }
137        );
138        assert_eq!(serde_json::to_string(&o2)?, r#"{"ext":{}}"#);
139
140        Ok(())
141    }
142}