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
use serde::{de, ser};
use serde_json::value::RawValue;
#[derive(Debug, Clone)]
pub struct Ext<'a>(&'a RawValue);
impl<'a> Ext<'a> {
pub fn try_from<'b>(raw: &'b RawValue) -> serde_json::Result<Ext<'a>>
where
'b: 'a,
{
check_raw(raw).map(Self).map_err(ser::Error::custom)
}
pub fn get(&'a self) -> &'a str {
self.0.get()
}
}
impl<'a> PartialEq for Ext<'a> {
fn eq(&self, other: &Self) -> bool {
self.0.get() == other.0.get()
}
}
impl<'a> ser::Serialize for Ext<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
}
impl<'de: 'a, 'a> de::Deserialize<'de> for Ext<'a> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let raw: &'a RawValue = de::Deserialize::deserialize(deserializer)?;
check_raw(raw).map(Self).map_err(de::Error::custom)
}
}
fn check_raw(raw: &RawValue) -> Result<&RawValue, &'static str> {
match raw.get().as_bytes().get(0) {
Some(b'{') | Some(b'n') => Ok(raw),
_ => Err("invalid value: expected null or object"),
}
}
#[cfg(test)]
mod test {
use super::*;
use serde::{Deserialize, Serialize};
use serde_json::{from_str, value::to_raw_value, Map, Value};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Object<'a> {
#[serde(borrow)]
ext: Ext<'a>,
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Extension<'a> {
f1: &'a str,
f2: i32,
}
#[test]
fn try_from_and_get() -> serde_json::Result<()> {
let object = Value::Object({
let mut m = Map::new();
m.insert("f1".into(), Value::String("abc".into()));
m.insert("f2".into(), Value::Number(123.into()));
m
});
let raw = to_raw_value(&object)?;
let ext = Ext::try_from(raw.as_ref())?;
let ext2 = from_str::<Extension>(ext.get())?;
assert_eq!(ext2, Extension { f1: "abc", f2: 123 });
Ok(())
}
#[test]
fn json() -> serde_json::Result<()> {
assert!(from_str::<Object>(r#"{"ext":null}"#).is_ok());
assert!(from_str::<Object>(r#"{"ext":true}"#).is_err());
assert!(from_str::<Object>(r#"{"ext":1}"#).is_err());
assert!(from_str::<Object>(r#"{"ext":"1"}"#).is_err());
assert!(from_str::<Object>(r#"{"ext":[1]}"#).is_err());
assert!(from_str::<Object>(r#"{"ext":{}}"#).is_ok());
let s1 = r#"{"ext":
null}"#;
let o1 = from_str::<Object>(s1)?;
assert_eq!(
o1,
Object {
ext: Ext::try_from(to_raw_value(&Value::Null)?.as_ref())?,
}
);
assert_eq!(serde_json::to_string(&o1)?, r#"{"ext":null}"#);
let s2 = r#"{"ext":
{}
}"#;
let o2 = serde_json::from_str::<Object>(s2)?;
assert_eq!(
o2,
Object {
ext: Ext::try_from(to_raw_value(&Value::Object(Default::default()))?.as_ref())?,
}
);
assert_eq!(serde_json::to_string(&o2)?, r#"{"ext":{}}"#);
Ok(())
}
}