ron icon indicating copy to clipboard operation
ron copied to clipboard

Struct with flatten field serialized as JSON, but not as struct

Open apatrushev opened this issue 1 year ago • 1 comments

Struct without flatten field serialized as struct:

use serde::{Deserialize, Serialize};
use serde_json::json;


#[derive(Debug, Deserialize, Serialize)]
struct Event {
    sender: String,
}


fn main() {
    let event = json!({
        "sender": "foobar",
    });
    let event = event.to_string();
    let event = serde_json::from_str::<Event>(&event).unwrap();
    let value = ron::to_string(&event).unwrap();
    println!("{}", value);
}

Result:

(sender:"foobar")

Struct containing flatten field serialized as JSON:

use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use serde_json::json;


#[derive(Debug, Deserialize, Serialize)]
struct Event {
    sender: String,

    #[serde(flatten)]
    extra: HashMap<String, String>,
}


fn main() {
    let event = json!({
        "sender": "foobar",
        "info": "test"
    });
    let event = event.to_string();
    let event = serde_json::from_str::<Event>(&event).unwrap();
    let value = ron::to_string(&event).unwrap();
    println!("{}", value);
}

Result:

{"sender":"foobar","info":"test"}

May be it would be better to see it as (literally ignore the flatten attribute for the fields on serialization may be optionally):

(sender:"foobar", extra: {"info":"test"})

apatrushev avatar Oct 01 '24 10:10 apatrushev

This is unfortunately serde's fault and ron cannot do anything about it.

When a struct contains any flattened fields, serde serializes it as a map (since serializing a struct requires having statically known field names) and not a struct. From ron's point of view, we just get a map from serde and have no idea that it was ever a struct.

juntyr avatar Oct 01 '24 10:10 juntyr

I just ran into this myself. It's disappointing to not be able to use flatten with RON.

Has there been any consideration for allowing RON's map syntax { } to be automatically coerced into a struct if the strings of the keys match the field names and the values they map to match the respective field types?

I understand this might not fully align with the intention of the syntax having an explicit distinction between structs and maps, but I might think of it as "maps with string keys can be treated as structs of anonymous type".

mxgrey avatar Jan 20 '25 11:01 mxgrey

Do you mean during serialization (unfortunately impossible since serde doesn't give us any information) or during deserialization (should already be working on the 0.9 pre-release version)?

juntyr avatar Jan 20 '25 11:01 juntyr

Thanks for pointing that out, I didn't think of trying the latest master. That does exactly what I was proposing, so that's great.

I did run into a separate bug while trying that out, so I've opened an issue ticket for that: #555

mxgrey avatar Jan 20 '25 13:01 mxgrey

Since this is an issue with serde, I'll close this issue

juntyr avatar Mar 23 '25 06:03 juntyr