Решением было бы объявить пользовательскую оболочку для Double
, которая знает, как декодировать себя из строк или двойных чисел:
struct DoubleLike: Decodable {
public let value: Double
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
value = try container.decode(Double.self)
} catch DecodingError.typeMismatch {
let valueString = try container.decode(String.self)
if let dbl = Double(valueString) {
value = dbl
} else {
throw DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "Could not convert \(valueString) to Double"))
}
}
}
}
Вы можете легко использовать это в своей структуре:
struct Nutriments: Decodable {
public let energy: DoubleLike
public let energyServing: DoubleLike
public let energy100g: DoubleLike
enum CodingKeys: String, CodingKey {
case energy
case energyServing = "energy_serving"
case energy100g = "energy_100g"
}
}
Преимущество этого решения в том, что оно масштабируемое, недостатком является то, что вам всегда нужно извлекать свойство .value
, прежде чем вы сможете использовать декодированный double.
Другоерешение будет включать в себя написание собственной Decoder
реализации, однако это может не стоить усилий.