Swift 4 JSONEncoder返回空的JSON数组

时间:2018-11-10 17:59:16

标签: ios swift xcode swift4 jsonencoder

我有多个要转换为JSON字符串的Codeable类。

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 :(得分:0)

您的推理是正确的,MyCodable没有属性,因此没有可读写的内容。您实际上偶然发现了快速JSON编码器和解码器的错误。他们不能很好地处理继承。因此,您的Product和Category类成为匿名的MyCodable类,无需进行任何编码或解码。

查看您的代码,我认为没有理由使用MyCodable类。只需让产品和类别遵守可编码协议即可。如果您需要能够以相同方式引用“产品”和“类别”的多态性,请定义一个遵循Codable的协议,并让“产品”和“类别”遵循您定义的协议。在我看来,这是多余的,但是在某些情况下,这是一个可行的解决方案。

答案 1 :(得分:0)

您的错误是您试图使用继承而不是泛型。您的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