Я использовал struct MyThing:Codable { }
для анализа JSON несколько раз. Теперь я хотел бы использовать class
вместо struct
, потому что struct
не совсем подходит для той работы, которую мне нужно выполнить (изменчивость, соответствие и т. Д.) И некоторого подкласса. Я попробовал это:
class Beverage:Codable{
var name:String = ""
}
class Beer:Beverage{
var alcoholPercent:Double = 0
}
Я не обязательно получаю список из нескольких различных типов напитков в одном и том же списке, скажем, я просто хочу расшифровать список [Beer]
. Если я попробую это с json с одним пивом, например {"name": "Hansa", "alcoholPercent": 5.4}
, и попытаюсь декодировать его в класс Beer, например:
let beer = try! JSONDecoder().decode(Beer.self, from: json.data(using: .utf8)!)
beer
будет иметь name: Hansa
и alcoholPercent: 0.0
. Имя правильное, но в качестве значения по умолчанию в классе являетсяcoholPercent.
Существует ли магический способ заставить подклассы автоматически соответствовать Codable
без явной установки ключа / значения для каждой переменной?
Это работает:
class Beverage:Codable{
var name:String = ""
}
class Beer:Beverage{
var alcoholPercent:Double = 0
enum CodingKeys:String, CodingKey{
case alcoholPercent
}
required init(from decoder: Decoder) throws {
let values = try! decoder.container(keyedBy: CodingKeys.self)
self.alcoholPercent = try! values.decode(Double.self, forKey: .alcoholPercent)
try super.init(from: decoder)
}
}
С этим кодом я получаю "Hansa"
и 5.4
.
Почему я должен явно соответствовать Codable
для подклассов, но не для базового класса, чтобы это работало? Есть ли способ сделать это без всего кода руководства? Я чувствую, что это должно было работать из коробки без необходимости требуемого инициализации.