4 releases
0.1.3 | Dec 26, 2024 |
---|---|
0.1.2 | Dec 26, 2024 |
0.1.1 | Dec 21, 2024 |
0.1.0 | Dec 21, 2024 |
#814 in Encoding
417 downloads per month
16KB
232 lines
Serde nested JSON
Summary and basic use
This is a small utility crate to help deal with nested JSON in structs.
Here's a basic example:
use serde::{Serialize, Deserialize};
use serde_json::{json, from_value, to_string_pretty};
use serde_nested_json;
let as_json = json!({
"someData": {
"foo": "bar",
"baz": 123
},
"nestedJson": "{\"foo\":\"bar\",\"baz\":123}"
});
#[derive(Serialize, Deserialize)]
struct SomeData {
foo: String,
baz: u32
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct MyStruct {
some_data: SomeData,
#[serde(with = "serde_nested_json")]
nested_json: SomeData
}
# println!("{}", to_string_pretty(&from_value::<MyStruct>(as_json).unwrap()).unwrap());
Optional values
Optional values deserialize just fine from "null"
, but if the value may be undefined please add default
field attribute:
use serde::{Serialize, Deserialize};
use serde_json::{json, from_value, to_string_pretty};
use serde_nested_json;
let as_json = json!({
"here": "\"hello!\"",
"null": "null",
// "undefined": _
});
#[derive(Serialize, Deserialize)]
struct MyStruct {
#[serde(with = "serde_nested_json")]
here: Option<String>,
#[serde(with = "serde_nested_json")]
null: Option<String>,
#[serde(with = "serde_nested_json", default)] // <-- default saves the day
undefined: Option<String>,
}
# println!("{}", to_string_pretty(&from_value::<MyStruct>(as_json).unwrap()).unwrap());
Vecs
There's also a helper module for vecs containing nested items.
To use it, Just add ::vec
to the with
field attribute:
use serde::{Serialize, Deserialize};
use serde_json::{json, from_value, to_string_pretty};
use serde_nested_json;
let as_json = json!({
"array": [
"{\"foo\":\"bar\",\"baz\":123}",
"{\"foo\":\"baz\",\"baz\":54321}"
]
});
#[derive(Serialize, Deserialize)]
struct SomeData {
foo: String,
baz: u32
}
#[derive(Serialize, Deserialize)]
struct MyStruct {
#[serde(with = "serde_nested_json::vec")]
array: Vec<SomeData>,
}
# println!("{}", to_string_pretty(&from_value::<MyStruct>(as_json).unwrap()).unwrap());
NestedJson<T>
The main helper type of this crate is NestedJson<T>
which
can be used without field annotation. You will however need
to extract and insert the inner value on your own:
use serde::{Serialize, Deserialize};
use serde_json::{json, from_value, to_string_pretty};
use serde_nested_json::NestedJson;
let as_json = json!({
"nestedJson": "{\"baz\":123}"
});
#[derive(Serialize, Deserialize)]
struct SomeData {
baz: u32
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct MyStruct {
nested_json: NestedJson<SomeData>
}
// NestedJson<T> implements From<T>, so you can use t.into()
// as well as NestedJson::from(t)
impl From<SomeData> for MyStruct {
fn from(value: SomeData) -> MyStruct {
MyStruct {
nested_json: value.into()
}
}
}
// There's also an associated `into` fn which returns T
// NestedJson::from is also available, but I havent found
// a way to associate it with with the std::conversion
// traits using stable features
impl From<MyStruct> for SomeData {
fn from(value: MyStruct) -> SomeData {
value.nested_json.into()
}
}
// NestedJson<T> also implements AsRef<T>:
impl AsRef<SomeData> for MyStruct {
fn as_ref(&self) -> &SomeData {
self.nested_json.as_ref()
}
}
let a = SomeData { baz: 32 };
let b: MyStruct = a.into();
let c: SomeData = b.into();
let d: NestedJson<SomeData> = c.into();
let e: SomeData = d.into();
let a = SomeData { baz: 32 };
let b = MyStruct::from(a);
let c = SomeData::from(b);
let d = NestedJson::<SomeData>::from(c);
// Sadly not possible without manual implementation:
// let e = SomeData::from(d);
# println!("{}", to_string_pretty(&from_value::<MyStruct>(as_json).unwrap()).unwrap());
Forwarded trait implementations
NestedJson<T>
implements the following traits for any type
T
that also implements them, but does not require any of them:
- Debug
- Clone
- PartialEq (and Eq)
- PartialOrd
- Ord
These should be enough at least for basic tests etc., but just open an issue if you need anything else.
# use serde_nested_json::NestedJson;
let stuff = NestedJson::from(vec!["hello"]);
let mut clone = stuff.clone();
assert_eq!(stuff, clone);
println!("{:?}", clone); // 'NestedJson(["hello"])'
clone.into().sort();
Dependencies
~0.7–1.6MB
~35K SLoC