What to do when you don't know possible variants for Enum

I'm learning Rust by writing a simple CLI that calls a weather API based on some user input (city/state). The problem that I'm experiencing is that the API returns different key/value pairs in the JSON object depending on what's available for the location requested. For example, I've already noticed that for some locations there is a wind gust speed that's returned in addition to a normal wind speed. My initial thought was that this would be a good use case for an Enum and I would have one variant with a gust property and another without. However, I don't really have any way to know all of the different variants that are possible - maybe for some locations I can't get humidity, maybe for others I can't get pressure, etc.

My structs look like this:

#[derive(Serialize, Deserialize, Debug)]
pub struct Wind {
    pub speed: f32,
    pub deg: i32,
    pub gust: f32
}

#[derive(Serialize, Deserialize, Debug)]
pub struct WeatherResponse {
    pub coord: Coords,
    pub weather: Vec<Weather>,
    pub base: String,
    pub main: Main,
    pub visibility: i32,
    pub wind: Wind,
    pub clouds: Clouds,
    pub dt: i32,
    pub sys: Sys,
    pub timezone: i32,
    pub id: i32,
    pub name: String,
    pub cod: i32
}

I'm using the json feature from reqwest to deserialize the response directly into the WeatherResponse struct like this:

let url = reqwest::Url::parse_with_params(url, &params)?;
let res: WeatherResponse = blocking::get(url)?.json()?;

This works fine as long as the response object from the API comes back with the gust key:

    "wind": {
        "speed": 16.11,
        "deg": 350,
        "gust": 23.02
    },

but sometimes it comes back without it:

    "wind": {
        "speed": 9.22,
        "deg": 360
    },

I'm not sure why you're speaking about enum, but anyway - if the field can be omitted from struct, just wrap it into the Option.

Can you elaborate on this? As mentioned in my post, I'm just learning so my knowledge is quite limited at the moment. I gather from your response that an Enum is not the appropriate way to handle this but I don't understand

just wrap it into the Option .

The reason I was thinking about an Enum is because I was thinking that the Wind struct would have different variants:

enum Wind {
    WindNoGust,
    WindWithGust
}

struct WindNoGust {
    speed: i32,
    deg: i32
}

struct WindWithGust {
    speed: i32,
    deg: i32,
    gust: i32
}

Then I could do some check of the response object to figure out which variant to include. I obviously realized quickly that this wasn't a feasible approach because I would end up with an endless number of variants based on all of the different ways the responses can come back from the API - hence the question here.

The suggestion with Option is the following:

#[derive(Serialize, Deserialize, Debug)]
pub struct Wind {
    pub speed: f32,
    pub deg: i32,
    pub gust: Option<f32>,
}

Then the option will be None if the field is missing. It is possible that you need to put #[serde(default)] on the gust field to make it work.

3 Likes

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.