Serde: Internally tagged enum problem

I thought using #[serde(tag = "type")] looked so easy! But I am confused.

Background: I am porting forward someone else's ancient Rust code. And learning a lot. It includes moving pre-serde deserialization to serde, and internal enum tagging is my current problem.

In reading this JSON:

[…]
    "materials": {
      "water": {
        "specular": 1,
        "diffuse": 0.9,
        "reflectance": 1,
        "texture": {
          "variant": "Color",       <- line 19
          "fields": ["#118"]
        }
[…]

I get the complaint:

thread 'main' panicked at src/main.rs:42:56:
called `Result::unwrap()` on an `Err` value: Error("unknown variant `variant`, expected `Checkboard3d` or `Color`", line: 19, column: 19)

So I added #[serde(tag = "variant")] to the TextureConfig struct.

Nope.

error: #[serde(tag = "...")] cannot be used with tuple variants

I thought that was its purpose.

Here is code that duplicates the complaint I get (and don't understand) Rust Playground

Thanks,

-kb

serde documentation says that

Using a #[serde(tag = "...")] attribute on an enum containing a tuple variant is an error at compile time.

Looking at your JSON, you have a variant member and a fields member, which suggests adjacent tagging, not internal. Try this instead

#[serde(tag = "variant", content = "fields")]
3 Likes

That fixes the complaint!

Tomorrow I need to reread the documentation…

Thanks,

-kb

Yes, so much clearer in the light of a new day. I wasn't understanding the three different ways to tag enums (well, four if we count "untagged").

  • Externally tagged: tag is the parent of the data.
  • Internally tagger: tag is inside the data, along with all the other fields.
  • Adjacently tagged: the tag is external to the data but is not the parent of the data; the data is grouped as one item and the tag is a sibling to that item. So someplace in between what serde calls "external" and "internal".

And to be complete, there is a fourth case:

  • Untagged: serde tries to infer a tag based on whether the data matches any of the cases.

I was distracted by the fact that my tag is external to the data (it is external, it is!!), but it is not what serde calls "externally tagged". And the error "cannot be used with tuple variants`" was not useful to me.

I suggest better terminology—and a more logical ordering—might have been something like "parent tagged", "sibling tagged", "internally tagged", and "untagged"…mutter, grumble. Also, the examples for "external" and "internal" and even "untagged" are all nicely parallel to each other. But the example for "adjacent" is completely different from the other three. Grrr.

This frustration aside, serde is pretty cool.

Thanks,

-kb

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.