子类数组解码为超类

问题描述

当我解码子类(RegularCard)的数组时,我得到了超类(Card)的数组。编码很好,我测试了一下,编码工作正常。但是,当我解码时,未调用解码子类(RegularCard)的函数。我的代码如下。我在另一则帖子中发现了以下错误:

17年6月25日更新:我最终向苹果提交了一个有关此的错误。 rdar:// 32911973-不幸的是,包含子类的超类数组的编码/解码周期:超类元素将导致该数组中的所有元素都被解码为超类(子类的init(from :)从未被调用,从而导致数据丢失或更糟)。

这是在此post中。

  $resultimg = str_replace("data:image/png;base64,","",$base64strImg);
        header('Content-Disposition: attachment;filename="test.png"');
        header('Content-Type: image/png');
        echo base64_decode($resultimg);

'''

解决方法

对我来说很好:

    let reg = RegularCard(id: 1,front: "yo",score: 20,back: "frf")
    let arr = [reg]
    let data = try! JSONEncoder().encode(arr)
    let arr2 = try! JSONDecoder().decode([RegularCard].self,from: data)
    print(type(of:arr2)) // Array<RegularCard>
    let what = arr2.first!
    print(what.id,what.front,what.score,what.back) // 1 yo 20 frf

请注意,我确实需要稍微更改您的代码;我将第二个CodingKeys更改为CodingKeys2,因为否则我无法编译您的代码。

class RegularCard : Card {
    var back: String
    
    init(id: Int,front : String,score: Int,back : String) {
        self.back = back
        super.init(id: id,front: front,score: score,cardType: .regular)
    }
    enum CodingKeys2 : String,CodingKey {
        case back
        case id
        case front
        case score
        case cardType
    }
    override func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys2.self)
        print("encoding Regular")
        try super.encode(to: encoder)
        try container.encode(back,forKey: .back)
    }
    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys2.self)
        print("decoding regular")
        back = try values.decode(String.self,forKey: .back)
        try super.init(from: decoder)
        
    }
}

不过,我确实明白你的意思;即使使用RegularCard,如果我们解码为Card,也无法将其恢复为RegularCard的值(不能向下转换)。我猜那只是Codable或泛型的本质。基本上,我的建议是不要这样做。

但是,在这种情况下,您可以尝试将其解码为RegularCard,如果不起作用,则尝试将其解码为Card。这样,您始终可以获得正确的答案。

let card = Card(id: 2,front: "hoo",score: 10,cardType: .regular)
let reg = RegularCard(id: 1,back: "frf")
let arr1 = [card]
let arr2 = [reg]
let data1 = try! JSONEncoder().encode(arr1)
let data2 = try! JSONEncoder().encode(arr2)

// first data1
do {
    let result1 = try JSONDecoder().decode([RegularCard].self,from: data1)
    print(result1)
} catch {
    let result2 = try JSONDecoder().decode([Card].self,from: data1)
    print(result2) // it's a Card
}

// now data2
do {
    let result1 = try JSONDecoder().decode([RegularCard].self,from: data2)
    print(result1) // it's a RegularCard
} catch {
    let result2 = try JSONDecoder().decode([Card].self,from: data2)
    print(result2)
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...