Api v2
This commit is contained in:
52
Sources/OpenFoodFactsSDK/Schemas/Nutriments.swift
Normal file
52
Sources/OpenFoodFactsSDK/Schemas/Nutriments.swift
Normal file
@@ -0,0 +1,52 @@
|
||||
import FoundationEssentials
|
||||
|
||||
@dynamicMemberLookup
|
||||
public struct Nutriments: Codable, Sendable {
|
||||
private var storage: [String: Double]
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: AnyCodingKey.self)
|
||||
var dict = [String: Double]()
|
||||
for key in container.allKeys {
|
||||
if let val = try? container.decode(Double.self, forKey: key) {
|
||||
dict[key.stringValue] = val
|
||||
} else if let valStr = try? container.decode(
|
||||
String.self, forKey: key), let val = Double(valStr)
|
||||
{
|
||||
dict[key.stringValue] = val
|
||||
}
|
||||
}
|
||||
self.storage = dict
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: AnyCodingKey.self)
|
||||
for (key, value) in storage {
|
||||
try container.encode(value, forKey: AnyCodingKey(stringValue: key))
|
||||
}
|
||||
}
|
||||
|
||||
/// Access any nutrient dynamically (e.g. `nutriments.energyKcal`)
|
||||
public subscript(dynamicMember member: String) -> Double? {
|
||||
// Convert camelCase "energyKcal" to snake_case "energy-kcal" or "energy_kcal" logic if needed
|
||||
// For V2, OFF often returns "energy-kcal_100g"
|
||||
let snake = member.camelCaseToSnakeCase()
|
||||
return storage[snake] ?? storage["\(snake)_100g"]
|
||||
?? storage["\(snake)_value"]
|
||||
}
|
||||
|
||||
// Specific standard getters
|
||||
public var energyKcal: Double? { self.storage["energy-kcal_100g"] }
|
||||
public var carbohydrates: Double? { self.storage["carbohydrates_100g"] }
|
||||
public var fat: Double? { self.storage["fat_100g"] }
|
||||
public var proteins: Double? { self.storage["proteins_100g"] }
|
||||
public var salt: Double? { self.storage["salt_100g"] }
|
||||
}
|
||||
|
||||
// Helper for String extension used above
|
||||
struct AnyCodingKey: CodingKey {
|
||||
var stringValue: String
|
||||
var intValue: Int?
|
||||
init(stringValue: String) { self.stringValue = stringValue }
|
||||
init?(intValue: Int) { return nil }
|
||||
}
|
||||
Reference in New Issue
Block a user