在 Swift 中使用 JSON 解码器在解析 JSON 时将空值转换为默认字符串
Convert null values to default strings in parsing JSON using JSONDecoder in Swift
我正在尝试使用 JSON 解码器解析 Swift 中的一些 JSON,其中 JSON 偶尔会有空值。我想改用默认值。
以下允许我处理它,但空值稍后会导致问题。
struct Book: Codable {
let title : String
let author: String?
}
有没有办法做类似的事情(以下不编译),也许使用初始化程序?:
struct Book: Codable {
let title : String
let author: String ?? "unknown"
}
感谢任何建议
这可以通过手动解码解决here。
另一种方法是让存储的属性准确反映数据,然后在提供非可选值的情况下计算 var。
struct Book: Codable {
let title : String
let author: String?
var displayAuthor: String {
return author ?? "unknown"
}
}
这可能有吸引力的另一个原因是,如果您需要在将来检查该值是否存在,它会保留可选值。
您可以使用自定义 init(decoder:)
方法定义来实现此目的。如果 try
失败,请使用 decodeIfPresent
API 并为 属性 提供您想要的默认值。或者您可以使用@dktaylor 提到的计算 属性 方法。这是您需要的代码:
struct Book {
let title : String
let author: String
enum CodingKeys: String, CodingKey {
case title, author
}
}
extension Book: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decode(String.self, forKey: .title)
author = try container.decodeIfPresent(String.self, forKey: .author) ?? "unknown"
}
}
您也可以使用 属性 包装器实现此目的:
@propertyWrapper
struct OnNil<T> {
let value: T
init(_ value: T) {
self.value = value
}
private var _wrappedValue: T?
var wrappedValue: T! {
get { _wrappedValue ?? value }
set { _wrappedValue = newValue }
}
}
struct SomeStruct {
let title : String
@OnNil("unknown")
let author: String!
}
像这样使用 属性 包装器的好处是您不必用实用方法弄脏您的对象,也不必 fiddle 使用解码函数。缺点显然是语法看起来有点奇怪,你必须使一些变量隐式解包可选,并且由于 属性 包装器的性质,它会使你的代码稍微难以调试。
我正在尝试使用 JSON 解码器解析 Swift 中的一些 JSON,其中 JSON 偶尔会有空值。我想改用默认值。 以下允许我处理它,但空值稍后会导致问题。
struct Book: Codable {
let title : String
let author: String?
}
有没有办法做类似的事情(以下不编译),也许使用初始化程序?:
struct Book: Codable {
let title : String
let author: String ?? "unknown"
}
感谢任何建议
这可以通过手动解码解决here。
另一种方法是让存储的属性准确反映数据,然后在提供非可选值的情况下计算 var。
struct Book: Codable {
let title : String
let author: String?
var displayAuthor: String {
return author ?? "unknown"
}
}
这可能有吸引力的另一个原因是,如果您需要在将来检查该值是否存在,它会保留可选值。
您可以使用自定义 init(decoder:)
方法定义来实现此目的。如果 try
失败,请使用 decodeIfPresent
API 并为 属性 提供您想要的默认值。或者您可以使用@dktaylor 提到的计算 属性 方法。这是您需要的代码:
struct Book {
let title : String
let author: String
enum CodingKeys: String, CodingKey {
case title, author
}
}
extension Book: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decode(String.self, forKey: .title)
author = try container.decodeIfPresent(String.self, forKey: .author) ?? "unknown"
}
}
您也可以使用 属性 包装器实现此目的:
@propertyWrapper
struct OnNil<T> {
let value: T
init(_ value: T) {
self.value = value
}
private var _wrappedValue: T?
var wrappedValue: T! {
get { _wrappedValue ?? value }
set { _wrappedValue = newValue }
}
}
struct SomeStruct {
let title : String
@OnNil("unknown")
let author: String!
}
像这样使用 属性 包装器的好处是您不必用实用方法弄脏您的对象,也不必 fiddle 使用解码函数。缺点显然是语法看起来有点奇怪,你必须使一些变量隐式解包可选,并且由于 属性 包装器的性质,它会使你的代码稍微难以调试。