У меня есть словарный массив JSON, и мне нужно декодировать его для создания типа данных (Hitter), объект Hitter должен содержать необработанные данные JSON, и мне нужно добавлять свойства в Hitter на протяжении всей жизни. из приложения. Я обнаружил, что мне нужно использовать init (из декодера :), но как правильно вызвать init? Я буду хранить Hitter в структуре League.
struct League {
var Hitters: Set<Hitter>
func loadHitters() {
...//ingest json from bundle,
//store decoded Hitter objects in temp array,
//then append each item from temp array into League.Hitters set.
}
}
Чтобы было ясно, мой У структуры Hitter уже есть инициализация, мне нужна помощь с использованием декодера с этого момента.
РЕДАКТИРОВАТЬ: Я нашел решение, и оно требует использования извлечения ключей JSON и связывания их с вашим CodingKeys enum. Вот мой сокращенный класс Hitter:
struct Hitter: Player, Decodable {
//partial list of properties in JSON data
let strPos: String
let OBP: Float
let wRAA: Float //weightedRunsAboveAverage
//partial list of properties in JSON data - end
//partial list of additional properties
var valAboveReplacement: Float = 0.0
var wOBP: Float {
return OBP * Float(PA)
}
//partial list of additional properties - end
}
Я объявляю CodingKeys и init (decoder :) в расширении для разделения
extension Hitter {
enum CodingKeys: String, CodingKey {
case strPos, OBP, wRAA
}
convenience init(from decoder: Decoder) {
//container links all the CodingKeys and JSONDecoder keys for proper referencing. Returns the data stored in this decoder as represented in a container keyed by the given key type
let container = try decoder.container(keyedBy: CodingKeys.self)
let strPos = try container.decode(String.self, forKey: .strPos)
let OBP = try container.decode(Float.self, forKey: .OBP)
let wRAA = try container.decode(Float.self, forKey: .wRAA)
//pass my decoded values via a standard initializer
self.init(strPos: strPos, OBP: OBP, wRAA: wRAA)
}
}
Кажется, это работает прекрасно, пока я явно связать формат JSON и CodingKeys через контейнер.