Codable for class with Inheritance
Codable for class with Inheritance
我正在尝试以下代码,但它抛出异常
import Foundation
class SomeBaseClass: Codable {
let someInt: Int?
let someString: String?
init(someInt: Int,someString:String) {
self.someInt = someInt
self.someString = someString
}
init(someBaseClass: SomeBaseClass) {
self.someString = someBaseClass.someString
self.someInt = someBaseClass.someInt
}
}
class Person: SomeBaseClass {
let firstName: String?
let lastName: String?
init(firstName: String,lastName:String,someBaseClass: SomeBaseClass) {
self.firstName = firstName
self.lastName = lastName
super.init(someBaseClass: someBaseClass)
}
enum CodingKeys: String, CodingKey {
case firstName,lastName
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
firstName = try container.decode(String.self, forKey: .firstName)
lastName = try container.decode(String.self, forKey: .lastName)
try super.init(from: container.superDecoder())
}
}
let json = """
{
"firstName":"John",
"someInt":2
}
"""
let jsonData = json.data(using: .utf8)!
do {
let personObject = try JSONDecoder().decode(Person.self, from: jsonData)
dump(personObject)
} catch let error as NSError {
print(error)
}
它因以下错误而崩溃
Error Domain=NSCocoaErrorDomain Code=4865 "No value associated with
key CodingKeys(stringValue: "lastName", intValue: nil) ("lastName")."
UserInfo={NSDebugDescription=No value associated with key
CodingKeys(stringValue: "lastName", intValue: nil) ("lastName").,
NSCodingPath=( )}
我知道 JSON 中缺少 lastName
,我已将其标记为可选,但它的工作方式与结构不同
有没有简单的方法可以做到这一点?
您应该使用 decodeIfPresent
作为您的可选属性
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
firstName = try container.decodeIfPresent(String.self, forKey: .firstName)
lastName = try container.decodeIfPresent(String.self, forKey: .lastName)
try super.init(from: decoder)
}
另请注意为避免另一个错误而需要对 super 的更改。您还可以从
稍微更改您的捕获量
} catch let error as NSError {
print(error)
}
简单地
} catch {
print(error)
}
我正在尝试以下代码,但它抛出异常
import Foundation
class SomeBaseClass: Codable {
let someInt: Int?
let someString: String?
init(someInt: Int,someString:String) {
self.someInt = someInt
self.someString = someString
}
init(someBaseClass: SomeBaseClass) {
self.someString = someBaseClass.someString
self.someInt = someBaseClass.someInt
}
}
class Person: SomeBaseClass {
let firstName: String?
let lastName: String?
init(firstName: String,lastName:String,someBaseClass: SomeBaseClass) {
self.firstName = firstName
self.lastName = lastName
super.init(someBaseClass: someBaseClass)
}
enum CodingKeys: String, CodingKey {
case firstName,lastName
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
firstName = try container.decode(String.self, forKey: .firstName)
lastName = try container.decode(String.self, forKey: .lastName)
try super.init(from: container.superDecoder())
}
}
let json = """
{
"firstName":"John",
"someInt":2
}
"""
let jsonData = json.data(using: .utf8)!
do {
let personObject = try JSONDecoder().decode(Person.self, from: jsonData)
dump(personObject)
} catch let error as NSError {
print(error)
}
它因以下错误而崩溃
Error Domain=NSCocoaErrorDomain Code=4865 "No value associated with key CodingKeys(stringValue: "lastName", intValue: nil) ("lastName")." UserInfo={NSDebugDescription=No value associated with key CodingKeys(stringValue: "lastName", intValue: nil) ("lastName")., NSCodingPath=( )}
我知道 JSON 中缺少 lastName
,我已将其标记为可选,但它的工作方式与结构不同
有没有简单的方法可以做到这一点?
您应该使用 decodeIfPresent
作为您的可选属性
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
firstName = try container.decodeIfPresent(String.self, forKey: .firstName)
lastName = try container.decodeIfPresent(String.self, forKey: .lastName)
try super.init(from: decoder)
}
另请注意为避免另一个错误而需要对 super 的更改。您还可以从
稍微更改您的捕获量} catch let error as NSError {
print(error)
}
简单地
} catch {
print(error)
}