How can I deserialize an enum when the case doesn't match?
Asked Answered
D

3

32

I have a JSON structure that looks like this:

{ "type": "suite", "event": "started", "test_count": 1 }

I want to deserialize into these structs:

#[derive(Debug, Deserialize)]
enum ResultType {
    Suite,
    Test,
}

#[derive(Debug, Deserialize)]
enum ResultEvent {
    Started,
    Failed,
    Ok,
}

#[derive(Debug, Deserialize)]
struct JsonResult {
    #[serde(rename(deserialize = "type"))]
    test_type: ResultType,
    event: ResultEvent,
    test_count: Option<u32>,
}

I can't find a way to make serde_json use the correct case. I keep getting these errors:

Error("unknown variant `suite`, expected `Suite` or `Test`", line: 1, column: 17)

If I change the case of the enum values to all lowercase or all uppercase it works, but I'd like to be able to use PascalCase.

Digiacomo answered 4/12, 2019 at 0:37 Comment(0)
S
56

You just need to put #[serde(rename_all = "snake_case")] before the enum definition.

Other possible values are lowercase, UPPERCASE, PascalCase, camelCase, snake_case, SCREAMING_SNAKE_CASE, kebab-case, and SCREAMING-KEBAB-CASE.

Sherlynsherm answered 4/12, 2019 at 1:50 Comment(1)
I needed lowercase but this is indeed the fix! Thank you!Digiacomo
T
10

If you want to support different capitalisations, you can add an alias on the enum variants:

enum ResultType {
    #[serde(alias="suite", alias="SUITE")]
    Suite,
    #[serde(alias="test", alias="TEST")]
    Test,
}

In this case, either "Suite", "suite" or "SUITE" is acceptable.

And any other case like "sUitE", there must be something wrong.

Tades answered 19/2, 2022 at 4:3 Comment(0)
D
8

Use #[serde(rename = "name")] to change the string used for the enum variant when serializing and deserializing.

#[derive(Debug, Deserialize)]
enum ResultType {
    #[serde(rename = "suite")]
    Suite,
    #[serde(rename = "test")]
    Test,
}

#[derive(Debug, Deserialize)]
enum ResultEvent {
    #[serde(rename = "started")]
    Started,
    #[serde(rename = "failed")]
    Failed,
    #[serde(rename = "ok")]
    Ok,
}

#[derive(Debug, Deserialize)]
struct JsonResult {
    #[serde(rename(deserialize = "type"))]
    test_type: ResultType,
    event: ResultEvent,
    test_count: Option<u32>,
}

You can also use #[serde(alias = "name")] to add an extra string to accept when deserializing.

Details are in the serde documentation: https://serde.rs/variant-attrs.html

Dobsonfly answered 8/6, 2021 at 1:46 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.