gpt4 book ai didi

json - 使用 Swift 4 中的 JSONDecoder,缺失的键可以使用默认值而不必是可选属性吗?

转载 作者:行者123 更新时间:2023-11-30 11:20:09 35 4
gpt4 key购买 nike

Swift 4 添加了新的 Codable 协议(protocol)。当我使用 JSONDecoder 时,它似乎要求我的 Codable 类的所有非可选属性都在 JSON 中包含键,否则会引发错误。

使我的类的每个属性可选似乎是不必要的麻烦,因为我真正想要的是使用 json 中的值或默认值。 (我不希望该属性为零。)

有办法做到这一点吗?

class MyCodable: Codable {
var name: String = "Default Appleseed"
}

func load(input: String) {
do {
if let data = input.data(using: .utf8) {
let result = try JSONDecoder().decode(MyCodable.self, from: data)
print("name: \(result.name)")
}
} catch {
print("error: \(error)")
// `Error message: "Key not found when expecting non-optional type
// String for coding key \"name\""`
}
}

let goodInput = "{\"name\": \"Jonny Appleseed\" }"
let badInput = "{}"
load(input: goodInput) // works, `name` is Jonny Applessed
load(input: badInput) // breaks, `name` required since property is non-optional

最佳答案

您可以在您的类型中实现 init(from detector: Decoder) 方法,而不是使用默认实现:

class MyCodable: Codable {
var name: String = "Default Appleseed"

required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let name = try container.decodeIfPresent(String.self, forKey: .name) {
self.name = name
}
}
}

您还可以将 name 设置为常量属性(如果您愿意):

class MyCodable: Codable {
let name: String

required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let name = try container.decodeIfPresent(String.self, forKey: .name) {
self.name = name
} else {
self.name = "Default Appleseed"
}
}
}

required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Default Appleseed"
}

回复您的评论:使用自定义扩展

extension KeyedDecodingContainer {
func decodeWrapper<T>(key: K, defaultValue: T) throws -> T
where T : Decodable {
return try decodeIfPresent(T.self, forKey: key) ?? defaultValue
}
}

你可以将 init 方法实现为

required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decodeWrapper(key: .name, defaultValue: "Default Appleseed")
}

但这并不比

短多少
    self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Default Appleseed"

关于json - 使用 Swift 4 中的 JSONDecoder,缺失的键可以使用默认值而不必是可选属性吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51346155/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com