Skip to content

Instantly share code, notes, and snippets.

@krisselden
Last active February 29, 2020 02:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krisselden/6e153ed3632a95929faedc1add7cf82a to your computer and use it in GitHub Desktop.
Save krisselden/6e153ed3632a95929faedc1add7cf82a to your computer and use it in GitHub Desktop.
flatten json RawValue
use serde::de::{Deserialize, Deserializer, MapAccess, Visitor};
use serde_json::value::RawValue;
use std::collections::HashMap;
use std::fmt;
use std::marker::PhantomData;
#[derive(Debug)]
struct TestA<'a> {
a: i32,
rest: HashMap<&'a str, &'a RawValue>,
}
fn main() {
let s = r#"{
"a": 42,
"b": "foo",
"c": [ 1, 2, { "x": 10, "y": 40 } ]
}"#;
let r = serde_json::from_str::<TestA>(s);
println!("{:#?}", r);
}
impl<'de: 'a, 'a> Deserialize<'de> for TestA<'a> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(deserializer.deserialize_map(TestAVisitor::new())?)
}
}
struct TestAVisitor<'a> {
marker: PhantomData<fn() -> TestA<'a>>,
}
impl<'a> TestAVisitor<'a> {
fn new() -> Self {
TestAVisitor {
marker: PhantomData,
}
}
}
impl<'de: 'a, 'a> Visitor<'de> for TestAVisitor<'a> {
type Value = TestA<'a>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("object json")
}
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: MapAccess<'de>,
{
let mut a = None;
let mut rest =
HashMap::with_capacity(access.size_hint().unwrap_or(0));
while let Some(key) = access.next_key()? {
match key {
"a" => {
a = Some(access.next_value()?);
}
_ => {
rest.insert(key, access.next_value()?);
}
}
}
let a = a.unwrap();
Ok(TestA { a, rest })
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment