首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有继承的JSONEncoder

具有继承的JSONEncoder
EN

Stack Overflow用户
提问于 2022-04-25 22:20:59
回答 1查看 38关注 0票数 0

我想在类播放器中使用JSONEncoder,它是在课后继承的。我得到错误“类型'Player.Type‘不能符合’可编码‘”。我找到了一些解决方案,但在这些情况下,JSON代码类似于使Person的变量类型。

人:

代码语言:javascript
复制
class Person: Codable {

    let name: String
    let surname: String
    let gender: Bool
    
    init(name: String, surname: String, gedner: Bool) throws {
        self.name = name
        self.surname = surname
        self.gender = gedner
    }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        surname = try container.decode(String.self, forKey: .surname)
        gender = try container.decode(Bool.self, forKey: .gender)
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(self.name, forKey: .name)
        try container.encode(self.surname, forKey: .surname)
        try container.encode(self.gender, forKey: .gender)
    }
    
    private enum CodingKeys: String, CodingKey {
            case name
            case surname
            case gender
    }
}

播放器:

代码语言:javascript
复制
class Player: Person {
    private(set) var number: Int
    
    init(name: String, surname: String, gedner: Bool, number: Int) throws {
        self.number = number
        try super.init(name: name, surname: surname, gedner: gedner)
    }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.number = try container.decode(Int.self, forKey: .number)
        try super.init(from: decoder) 
    }
    
    override func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(number, forKey: .number)
        try container.encode(name, forKey: .name)
        try container.encode(surname, forKey: .surname)
        try container.encode(gender, forKey: .gender)
     
    }
    
    private enum CodingKeys: String, CodingKey {
        case number
        case name
        case surname
        case gender
    }
}

代码:

代码语言:javascript
复制
let newPlayer = try Player(name: "Name", surname: "Surname", gedner: true, number: 21)
let data = try encoder.encode(Player) //Error: Type 'Player.Type' cannot conform to 'Encodable'
EN

回答 1

Stack Overflow用户

发布于 2022-04-25 22:55:34

为了澄清罗布说了些什么,再加上几个建议:

  • 解码时,需要提供一个类型。当编码时,需要提供一个对象:

代码语言:javascript
复制
let newPlayer = try Player(name: "Name", surname: "Surname", gedner: true, number: 21)

let encoder = JSONEncoder()
// Provide object
let data = try encoder.encode(newPlayer)

let decoder = JSONDecoder()
// Provide type (and data)
let decodedPlayer = try decoder.decode(Player.self, from: data)

  • 如果事情像您在Person中描述的那样简单,那么Person不需要任何自定义编码/解码,您可以依赖于合成的编码/解码:

代码语言:javascript
复制
class Person: Codable {

    let name: String
    let surname: String
    let gender: Bool

    init(name: String, surname: String, gedner: Bool) throws {
        self.name = name
        self.surname = surname
        self.gender = gedner
    }
}

上述代码将生成与自定义代码相同的编码/解码。

  • 用于子类,您总是需要指定自定义编码和解码,但只用于与父类不同的内容。例如,您不需要复制键,也不需要对其类进行编码。就像使用super.init一样,使用super.encode。所以代码变成:

代码语言:javascript
复制
class Player: Person {
    private(set) var number: Int

    init(name: String, surname: String, gedner: Bool, number: Int) throws {
        self.number = number
        try super.init(name: name, surname: surname, gedner: gedner)
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.number = try container.decode(Int.self, forKey: .number)
        try super.init(from: decoder)
    }

    override func encode(to encoder: Encoder) throws {
        try super.encode(to: encoder)
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(number, forKey: .number)
    }

    private enum CodingKeys: String, CodingKey {
        case number
    }
}

与编码/解码无关

如评论中提到的@LeoDabus所述,Player.init(name: String...中的

  • 看起来不像您的initPerson中会抛出任何异常,因此您可能希望从Person.initthrows中删除throws

您还可能希望将参数名从gender更正为

代码语言:javascript
复制
class Person: Codable {

    let name: String
    let surname: String
    let gender: Bool

    init(name: String, surname: String, gender: Bool) {
        self.name = name
        self.surname = surname
        self.gender = gender
    }
}

代码语言:javascript
复制
class Player: Person {
    private(set) var number: Int

    init(name: String, surname: String, gender: Bool, number: Int) {
        self.number = number
        super.init(name: name, surname: surname, gender: gender)
    }
    // ...
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72006306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档