简体   繁体   中英

Serde Stream Deserializer for a type other than serde_json::Value

I want to parse a JSON string of the form

{
    "a": {
        "foo": "bar"
    },
    "b": {
        "foo": "baz"
    }
}

That is, at the top level there are a number of JSON objects separated by commas. Each of these objects have the same fields as the others (ie, I can easily represent all of these objects with a single struct ).

Since there are several of these objects in the JSON string, I believe I should be using a serde_json::StreamDeserializer , though I am relatively new to Rust and serde in particular, so if this is not the right approach, please point me in the correct direction.

This code represents what I want to do:

use serde_json::Deserializer;
use serde::Deserialize;

#[derive(Deserialize, Debug)]
struct Data {
    foo: String,
}

fn main() {
    let data = r#"{
        "a": {"foo": "bar"},
        "b": {"foo": "baz"}
    }"#;

    let stream = Deserializer::from_str(data).into_iter::<Data>();

    for value in stream {
        println!("{:?}", value.unwrap());
    }
}

I would expect this code to produce some output similar to Object({"a": Object({"foo": String("bar")}), "b": Object({"foo": String("baz")})}) .

This is the output I see if I change Deserializer::from_str(data).into_iter::<Data>(); to Deserializer::from_str(data).into_iter::<serde_json::Value>(); .

Instead, the code fails to compile, giving the error Error("missing field 'foo'", line: 4, column: 5)

So, what do I need to do in order to deserialize the JSON into Data structs rather than Value ?

Turns out the solution was much simpler than I thought. Credit to /u/sfackler on Reddit for pointing this out to me .

In this scenario, I don't need to use a StreamDeserializer ; instead, I can just parse the JSON into a HashMap and extract the values I want from it.

For example:

use serde::Deserialize;
use std::collections::HashMap;

#[derive(Deserialize, Debug)]
struct Data {
    foo: String,
}

fn main() {
    let data = r#"{
        "a": {"foo": "bar"},
        "b": {"foo": "baz"}
    }"#;

    let m: HashMap<String, Data> = serde_json::from_str(&data).unwrap();
    for (_key, val) in m {
        println!("{:?}", val);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM