public struct Ingredient: Sendable, Codable { public var fromPalmOil: String? = nil public var id: String? = nil public var origin: String? = nil public var percent: Float? = nil public var rank: Float? = 0 public var text: String? = nil public var vegan: String? = nil public var vegetarian: String? = nil public var ciqualFoodCode: String? = nil public var ecobalyseCode: String? = nil public var percentEstimate: Float? = nil // String or number private enum CodingKeys: String, CodingKey { case fromPalmOil = "from_palm_oil" case id case origin case percent case rank case text case vegan case vegetarian case ciqualFoodCode = "ciqual_food_code" case ecobalyseCode = "ecobalyse_code" case percentEstimate = "percent_estimate" } public var isWater: Bool { ciqualFoodCode == "18066" } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // Standard String fields id = try container.decodeIfPresent(String.self, forKey: .id) text = try container.decodeIfPresent(String.self, forKey: .text) vegan = try container.decodeIfPresent(String.self, forKey: .vegan) vegetarian = try container.decodeIfPresent( String.self, forKey: .vegetarian) fromPalmOil = try container.decodeIfPresent( String.self, forKey: .fromPalmOil) origin = try container.decodeIfPresent(String.self, forKey: .origin) ciqualFoodCode = try container.decodeIfPresent( String.self, forKey: .ciqualFoodCode) ecobalyseCode = try container.decodeIfPresent( String.self, forKey: .ecobalyseCode) // Polymorphic Fields (String or Number) percentEstimate = try container.decodeFloatOrString( forKey: .percentEstimate) percent = try container.decodeFloatOrString(forKey: .percent) rank = try container.decodeFloatOrString(forKey: .rank) } }