Q:

How can i decode JSON data field that are of changeable types?

I'm receiving JSON data from an API but there are some fields that sometimes are strings and other times are integers. What are the best solutions for something like that?
Here is my decode code:
public struct Nutriments {
    public let energy: String?
    public let energyServing: String?
    public let energy100g: String?

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        energy = try container.decodeIfPresent(String.self, forKey: .energy)
        energy100g = try container.decodeIfPresent(String.self, forKey: .energy100g)
        energyServing = try container.decodeIfPresent(String.self, forKey: .energyServing)
        }
}

JSON example:
"nutriments": {
        "energy_100g": 8.97,
        "energy_serving": "55",
        "energy": "7"
}

And other times like this:
"nutriments": {
        "energy_100g": "8.97",
        "energy_serving": 55,
        "energy": 7
}

A:

First of all blame the owner of the service for sending inconsistent data.
To decode both types you can check the type in the init method.
At least the API seems to send all keys so you can declare all struct members as non-optional
public struct Nutriments {

    public let energy: String
    public let energyServing: String
    public let energy100g: String

    public init(from decoder: Decoder) throws {      
        let container = try decoder.container(keyedBy: CodingKeys.self)
        do { energy = try container.decode(String.self, forKey: .energy) }
        } catch DecodingError.typeMismatch { energy = String(try container.decode(Int.self, forKey: .energy)) }
        do { energy100g = try container.decode(String.self, forKey: .energy100g) }
        } catch DecodingError.typeMismatch { energy100g = String(try container.decode(Int.self, forKey: .energy100g)) }
        do { energyServing = try container.decode(String.self, forKey: .energyServing) }
        } catch DecodingError.typeMismatch { energyServing = String(try container.decode(Int.self, forKey: .energyServing)) }
    }
}

