1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use serde::{de, ser, Deserialize, Serialize};
use serde_json::{Map, Value};
use std::convert::{From, Into};
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Clone)]
pub struct Ext(Map<String, Value>);
impl Ext {
pub fn try_from<T>(value: T) -> serde_json::Result<Self>
where
T: Serialize,
{
match serde_json::to_value(value)? {
Value::Object(m) => Ok(Self(m)),
_ => Err(ser::Error::custom(
"must pass a value that can be converted to `serde_json::Map`",
)),
}
}
pub fn try_into<T>(self) -> serde_json::Result<T>
where
T: de::DeserializeOwned,
{
serde_json::from_value(Value::Object(self.0))
}
}
impl From<Map<String, Value>> for Ext {
fn from(value: Map<String, Value>) -> Self {
Self(value)
}
}
impl Into<Map<String, Value>> for Ext {
fn into(self) -> Map<String, Value> {
self.0
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn from_and_into() {
let m = Map::new();
let e: Ext = m.into();
let _: Map<String, Value> = e.into();
}
#[test]
fn try_from_and_try_into() -> serde_json::Result<()> {
assert!(Ext::try_from(serde_json::json!(true)).is_err());
let ext = Ext::try_from(serde_json::json!({"a": 1}))?;
assert_eq!(
ext,
Ext({
let mut m = Map::new();
m.insert("a".into(), Value::Number(1.into()));
m
}),
);
assert_eq!(ext.try_into::<Value>()?, serde_json::json!({"a": 1}));
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Object {
f1: bool,
f2: i32,
}
let ext = Ext::try_from(Object { f1: true, f2: 123 })?;
assert_eq!(
ext,
Ext({
let mut m = Map::new();
m.insert("f1".into(), Value::Bool(true));
m.insert("f2".into(), Value::Number(123.into()));
m
})
);
assert_eq!(ext.try_into::<Object>()?, Object { f1: true, f2: 123 });
Ok(())
}
#[test]
fn json() -> serde_json::Result<()> {
let json = r#"{"a":1}"#;
let ext: Ext = serde_json::from_str(json)?;
assert_eq!(
ext,
Ext({
let mut m = Map::new();
m.insert("a".into(), Value::Number(1.into()));
m
})
);
assert_eq!(serde_json::to_string(&ext)?, json);
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Object {
ext: Ext,
}
let json = r#"{"ext":{"a":true}}"#;
let obj: Object = serde_json::from_str(json)?;
assert_eq!(
obj,
Object {
ext: Ext({
let mut m = Map::new();
m.insert("a".into(), Value::Bool(true));
m
})
}
);
assert_eq!(serde_json::to_string(&obj)?, json);
Ok(())
}
}