26

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.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
CaseyB
  • 24,780
  • 14
  • 77
  • 112

3 Answers3

45

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.

timlyo
  • 2,086
  • 1
  • 23
  • 35
Coder-256
  • 5,212
  • 2
  • 23
  • 51
5

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

M. Leonhard
  • 1,332
  • 1
  • 18
  • 20
5

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.

Matt Ryall
  • 9,977
  • 5
  • 24
  • 20
govo
  • 452
  • 6
  • 11