Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serializing struct to JSON and then deserialing JSON back to struct fails. #1051

Closed
jsdw opened this issue Aug 3, 2023 · 2 comments
Closed

Comments

@jsdw
Copy link

jsdw commented Aug 3, 2023

In this example (playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=31652345ee158b7c7bbe31aa6c165c4f), I serialize some struct to JSON and then try to deserialize that JSON immediately back to the same struct. The serializing works as hoped, but I hit an error on deserializing. The code:

use serde_json::value::RawValue;

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct Response {
    pub jsonrpc: String,
    pub id: String,
    #[serde(flatten)]
    pub body: ResponseBody
}

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum ResponseBody {
    #[serde(rename = "result")]
    Result(Box<RawValue>)
}

fn main() {
    let res = Response {
        id: "123".into(),
        jsonrpc: "2.0".into(),
        body: ResponseBody::Result(RawValue::from_string("[1,2,3]".to_owned()).unwrap())
    };

    // This works as expected and looks good:
    let str =  serde_json::to_string_pretty(&res).unwrap();
    println!("{str}");

    // But trying to deserialize this straight back to the struct fails; bug?
    let _res: Response = serde_json::from_slice(
        str.as_bytes()
    ).expect("ok response");
}

The error I hit when I try to serde_json::from_slice is:

Error("invalid type: newtype struct, expected any valid JSON value", line: 5, column: 1)'

Quite possibly I'm just missing something, but I'd expect offhand that if I serialize some struct to JSON, it should be deserializable back into the struct again. Any pointers would be greatly appreciated :)

@dtolnay
Copy link
Member

dtolnay commented Aug 3, 2023

You are not going to be able to deserialize a RawValue inside of flatten. Flattened content is collected into intermediate data structures while the rest of the outer data structure is deserialized, so it's no longer associated with any of the original underlying JSON formatting for the RawValue's contents to mirror.

You can see why this happens by considering the following example:

#[derive(Deserialize, Debug)]
struct Repro {
    id: String,
    #[serde(flatten)]
    value: Box<RawValue>,
}

fn main() {
    let j = r#" {"a":1, "id":"...", "b":2} "#;
    serde_json::from_str::<Repro>(j).unwrap();
}

The "correct" value for value would be a JSON object containing "a":1 and "b":2, and no "id". This is what you have if value were serde_json::Value. But such a raw object does not appear anywhere in the input, so there can't exist a RawValue with that value.

@dtolnay dtolnay closed this as completed Aug 3, 2023
@jsdw
Copy link
Author

jsdw commented Aug 4, 2023

Thank you for the prompt reply; that makes perfect sense!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants