JSONEncoder Swift 4 возвращает пустой массив JSON - PullRequest
0 голосов
/ 10 ноября 2018

У меня есть несколько классов Codeable, которые я хочу преобразовать в строки JSON.

class MyCodable: NSObject, Codable {

    override init() {

    }

    func encode(to encoder: Encoder) throws {

    }

}

class Category: MyCodable {

   required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self);
        //... assign values and call super.init
    }

    override func encode(to encoder: Encoder) throws {

    }

    var categoyId: Int64;
    var categoryName: String;

    enum CodingKeys: String, CodingKey {
        case categoryId
        case categoryName
    }

}

class Product: MyCodable {

    required init(from decoder: Decoder) throws {
        //..assign values and call super.init
    }

    override func encode(to encoder: Encoder) throws {

    }

    var productId: Int64;
    var categoryId: Int64;
    var productName: String;

    enum CodingKeys: String, CodingKey {
        case productId
        case categoryId
        case productName
    }

}

У меня есть служебный класс, который я использую для преобразования.

class JSONUtil: NSObject {

    public static func encode(objects: [MyCodable]) -> String {
        var json: String = "";
        do {
            let encoder = JSONEncoder();
            encoder.outputFormatting = .prettyPrinted;
            let jsonData = try encoder.encode(objects);
            json = String(data: jsonData, encoding: String.Encoding.utf8)!
        } catch let convertError { json = "[{error: '" + convertError.localizedDescription + "'}]"; }
        return json;
    }

    public static func toJson(object: MyCodable) -> String {
        var objects = [MyCodable]();
        objects.append(object);
        return encode(objects: objects);
    }

}

Возвращаемое значение всегда "[{}]" независимо от того, что находится внутри массива объектов MyCodable. Во время отладки я вижу, что значения объекта Category заполнены.

Поскольку MyCodable не имеет свойств, поэтому JSONEncoder не распечатывает свойства категории? .. Или почему он не печатает свойства категории?

У меня такая же проблема с объектом Product.

Цель состоит в том, чтобы избежать необходимости настраивать преобразование JSON для каждого класса, который я хочу напечатать в JSON.

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Ваша ошибка в том, что вы пытаетесь использовать наследование вместо родовых. Ваш JSONUtil класс должен выглядеть следующим образом.

class JSONUtil: NSObject {

    public static func encode<T: Encodable>(objects: [T]) -> String {
        var json: String = "";
        do {
            let encoder = JSONEncoder();
            encoder.outputFormatting = .prettyPrinted;
            let jsonData = try encoder.encode(objects);
            json = String(data: jsonData, encoding: String.Encoding.utf8)!
        } catch let convertError { json = "[{error: '" + convertError.localizedDescription + "'}]"; }
        return json;
    }

    public static func toJson<T: Encodable>(object: T) -> String {
        return encode(objects: [object]);
    }

}

Я не уверен, почему вы создаете классы, наследуемые от NSObject. Возможно, вы застряли в старых способах Objective-C. ? Предпочитайте использовать struct вместо class, если вам не требуется копировать объект по ссылке.

0 голосов
/ 10 ноября 2018

Ваши рассуждения верны, MyCodable не имеет свойств, поэтому читать и писать нечего. Вы действительно наткнулись на ошибку быстрых JSON Encoder и Decoder. Они плохо справляются с наследованием. Таким образом, ваш класс Product и Category становится анонимным классом MyCodable, которому нечего кодировать или декодировать.

Глядя на ваш код, я не вижу причин для класса MyCodable. Просто сделайте, чтобы Продукт и Категория придерживались протокола Codable. Если вам нужен полиморфизм возможности ссылаться на продукт и категорию одинаковым образом, определите протокол Proocl, который соответствует Codable, и пусть продукт и категория придерживаются протокола, который вы определили. На мой взгляд, это излишне, но могут быть случаи, когда это приемлемое решение.

...