Serde: Allow integer tags for internally tagged enums

Created on 3 Feb 2017  路  12Comments  路  Source: serde-rs/serde

See this use case.

Would the internally tagged enum support allow me to handle schema versioning defined like this?

{
    "schema_version": 1,
    ...
}

I've never gotten a good answer about how I'd do that with Serde.

cc @ssokolow

derive enhancement

Most helpful comment

Attributes support non-string literals now right? This could be as simple as allowing:

#[derive(Serialize, Deserialize)]
#[serde(tag = "schema_version")]
enum E {
    #[serde(rename = 1)]
    V1(...),
    #[serde(rename = 2)]
    V2(...),
}

All 12 comments

Attributes support non-string literals now right? This could be as simple as allowing:

#[derive(Serialize, Deserialize)]
#[serde(tag = "schema_version")]
enum E {
    #[serde(rename = 1)]
    V1(...),
    #[serde(rename = 2)]
    V2(...),
}

Also boolean tags?

#[derive(Serialize, Deserialize)]
#[serde(tag = "error")]
enum Response {
    #[serde(rename = false)]
    Ok(QueryResult),
    #[serde(rename = true)]
    Err(QueryError),
}

Any plans to progress on this feature? I could give it a try, but I would need a bit of mentoring / pointing to the right places.

I have not started working on this. I would love a PR! Happy to provide guidance if you run into any trouble.

Any updates on this?

Hi :smile:
We need this feature for sozu #240 to handle configuration versioning.

I'd like to implement it. I saw that someone (#973) started working on it but abandoned it.
Can I use it as a starting point or do you recommend another approach ?

@NotBad4U You can use a string tag (the version enum's variant name) for the configuration version.

@NotBad4U I think #973 is the right approach. Literals in attributes will be stable in rust 1.30 so we can support #[serde(rename = 0)].

For what it's worth, I think there's an additional use case for this (though it's technically not for internally tagged enums, it'd hopefully be fixed the same way): #[repr(i32)] enums and the like.

Right now my solution is https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9154cf599592144c4473903b57d91abe ; but that's an awful lot of boilerplate for this simple use case :)

@Ekleog: I was able to use the serde_repr crate suggested by official docs to shorten your playground to this:

//! ```cargo
//! [dependencies]
//! serde = "1"
//! serde_repr = "0.1"
//! serde_json = "1"
//! ```

use std::fmt;

#[derive(Copy, Clone, Debug, serde_repr::Serialize_repr, serde_repr::Deserialize_repr)]
#[repr(i32)]
pub enum Test {
    Foo = 0,
    Bar = 2,
}

fn main() {
    println!("{}", serde_json::to_string(&Test::Foo).unwrap());
    println!("{:?}", serde_json::from_str::<Test>("0").unwrap());
}

This looks cool! I hadn't seen that in the docs when writing that message. Thank you!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dtolnay picture dtolnay  路  3Comments

kleimkuhler picture kleimkuhler  路  3Comments

dtolnay picture dtolnay  路  3Comments

Yamakaky picture Yamakaky  路  3Comments

spease picture spease  路  3Comments