Можно ли использовать Codable подклассы без явного декодирования? - PullRequest
0 голосов
/ 28 мая 2019

Я использовал 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 для подклассов, но не для базового класса, чтобы это работало? Есть ли способ сделать это без всего кода руководства? Я чувствую, что это должно было работать из коробки без необходимости требуемого инициализации.

1 Ответ

3 голосов
/ 28 мая 2019

То, что вы запрашиваете, это синтез компилятором переопределения init(from:) в Beer.Свифт не делает этого.Это обсуждалось на форуме Swift, например в этой теме .Итай Фербер (Itai Ferber) - главный инженер Apple, отвечающий за разработку и реализацию Codable, поэтому вы можете считать его ответ авторитетным.

Если вы удалите соответствие Codable из Beverage и добавите его к Beerнепосредственно (и к любым другим листовым подклассам Beverage), тогда вы можете получить поведение, которое вы хотите.Это сработает только в том случае, если вам не нужно соответствие самой Beverage.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...