Flattening an enum struct with serde

Hi,

I'm trying to implement a way to serialize an enum with various structs into json, but running into some issues with using the flatten command. Here's my enum:

enum E {
    Type1,
    Type2 {
        foo: String
    },
    Type3 {
        foo: String,
        bar: String
    }
}

I'd like to find a way to serialize this into something like:

// Type 1
{type: "1"}

//Type 2 (with foo = "A")
{type: "2", foo: "A"}

//Type 3 (with foo = "A" and bar = "B")
{type: "3", foo: "A", bar: "B"}

Is there anyway to do this with the built in attributes? I can generate the field type by adding a tag to the enum, and I can rename the enum-structs with the rename attribute, but can't figure out how to flatten the enum-structs

Just pointing out that I came across this earlier post, which is similar, but only covers the deserialization step: Serde_json: Flatten nested internally-tagged enums?
It is also a bit old now, so wasn't sure if things have changed since then

Does using the internally tagged enum representation not work? From what I can tell it covers your use case exactly:

#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
enum Message {
    Request { id: String, method: String, params: Params },
    Response { id: String, result: Value },
}

becomes

{"type": "Request", "id": "...", "method": "...", "params": {...}}

In combination with #[serde(rename = "1")], #[serde(rename = "2")], etc. on each enum variant, I think you should be able to get your desired behavior.


Edit: this:

#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
enum E {
    #[serde(rename = "1")]
    Type1,
    #[serde(rename = "2")]
    Type2 {
        foo: String
    },
    #[serde(rename = "3")]
    Type3 {
        foo: String,
        bar: String
    }
}

serializes to:

{
  "type": "2",
  "foo": "A"
}

(playground)

Ah, yeah, that should totally work actually. For some reason I was thinking that I needed Type1 to expand to {type: "1", foo: "", bar: ""} to denote the missing field, but I don't. And I also didn't include that part in my original post which wasn't very helpful.

In any case, this covers my use case, thank you!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.