How to Use Multiple Types for A Field in Serde JSON?

Telegram bot API responds as below*:

// this JSON will have comments, thus invalid
{
  "ok": true,
  "error_code": 404,  // if "ok" is false. can be absent.
  "description": null,  // if "ok" is false. can be null.
  "result": { ... }  // if "ok" is true. it has types.
}

result key has possible types, one of which is User. Assuming I derive Deserialize for a User struct I create as below:

#[derive(Deserialize)]
struct User {
    // fields of User here, see link above
}

...and presumably all the other types of Telegram bot API. And a struct called GenericResponse:

#[derive(Deserialize)]
struct GenericResponse {
    ok: bool,
    error_code: u32,
    description: String,
    result:  // so what is this going to be?
}

It will has many types. How can you deal with a key having multiple possible types?

1 Like

If there's no indication (besides structure) of result's type, you can use the untagged enum representation. This will try deserializing to each variant in turn until a matching one is found:

#[derive(Deserialize)]
struct GenericResponse {
    ok: bool,
    error_code: u32,
    description: String,
    result: GenericResponseResult
}

#[derive(Deserialize)]
#[serde(untagged)]
enum GenericResponseResult {
    User(User),
    // Other possible response types here...
}
7 Likes

The documentation rather tells:

Response { id: String, result: Value }

...instead of...

Response(Response)

Are you sure it is User(User)?

If I'm not mistaken, you can either define the User type inline as an enum variant:

#[derive(Deserialize)]
#[serde(untagged)]
enum GenericResponseResult {
    User { user_field_1: String },
}

Or seperately:

#[derive(Deserialize)]
#[serde(untagged)]
enum GenericResponseResult {
    User(User),
}

#[derive(Deserialize)]
struct User {
    user_field_1: String,
}

And they'll be deserialized the same. Depends if you ever want to use User seperately from GenericResponseResult.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.