rustenumsjsonresponse

Modeling API JSON response with enum when there are too many variants in Rust


My question is pretty simple - what are the ways I can model a JSON response of, e.g., stock prices. Let's say I want to model a JSON response of a price query request that gives me stock names and prices, like:

{"AAPL": {"usd": 10}, "GOOG": {"usd": 20} ...}

If I model this with an enum together with serde crate, it will require me to list a huge number of stock variants, and even if I'll somehow manage to do that, it will still be very inefficient because new stocks are added constantly and I won't be able to properly maintain the variants list. So the following is not feasible:

#[derive(Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum PriceResponse {
    AAPL(HashMap<String, HashMap<String, f32>>),
    GOOG(HashMap<String, HashMap<String, f32>>),
    ...
    ...
}

I do want to make use of rust's type system to make the response more "typed", but I don't know how to do it. Ideally, I want to get an enum or a struct back.


Solution

  • If I understand you, your data is of the format HashMap<String, HashMap<String, f32>> but you want to parse it into something with types that are more representative of the data. Could you define structs that represent your data but are not enums? Enums are for when the data can take different forms or have different meanings, but in this case every stock seems semantically the same. According to the serde documentation, you won't need to do extra work to get serde to deserialize the inner field.

    struct Stock(pub String);
    struct CurrencyName(pub String);
    struct Price(pub i32); // currencies are typically stored as integer
    struct StockResponse(pub Hashmap<Stock, HashMap<CurrencyName, Price>>);