可以是数组或字符串的自定义 Decodable 类型
Custom Decodable type that can be an Array or a String
一个API我处理returns要么:
{
"title": "Hello World"
}
或
{
"title": [{
"text": "Hello World"
}]
}
我的想法是 struct TitleStringValue
有一个自定义解码器,像这样:
struct TitleStringValue: Decodable {
let text: String
struct TitleStringValueInner: Decodable {
let text: String
}
init(from decoder: Decoder) throws {
if let stringContainer = try? decoder.singleValueContainer() {
text = try stringContainer.decode(String.self)
} else {
var arrayContainer = try decoder.unkeyedContainer()
text = try arrayContainer.decode(TitleStringValueInner.self).text
while !arrayContainer.isAtEnd {
_ = try? arrayContainer.decode(TitleStringValueInner.self)
}
}
}
}
struct MyResult: Decodable {
let title: TitleStringValue
}
但是在 title 由数组组成的情况下,TitleStringValue init(from decoder: Decoder)
从未被调用,因为解码器之前失败,遇到一个需要单一值类型的数组。
有办法解决吗?
我可以在我的 MyResult 结构级别上实现解码,但这意味着每个具有 TitleStringValue
s 的结构都需要一个自定义解码器,所以我更愿意在 TitleStringValue 级别上实现它。
我的建议是在这两种情况下都保留 title
属性。
首先尝试解码String
。如果这无法解码 Text
的数组(我保持名称简单)获取第一项并将 text
值分配给 title
.
struct Title: Decodable {
struct Text : Decodable { let text : String }
let title : String
private enum CodingKeys : String, CodingKey { case title }
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
do {
title = try container.decode(String.self, forKey: .title)
} catch DecodingError.typeMismatch {
let textArray = try container.decode([Text].self, forKey: .title)
title = textArray.first?.text ?? ""
}
}
}
这里的问题是 singleValueContainer 也可用于解码数组。因此,您得到的错误是由 TitleStringValue
的 init(from:)
函数内部的第二个 try
产生的,而不是之前的
话虽如此,您可以像这样进一步简化您的自定义解码:
struct TitleStringValue: Decodable {
let text: String
struct TitleStringValueInner: Decodable {
let text: String
}
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let string = try? container.decode([TitleStringValueInner].self).first?.text {
text = string
} else {
text = try container.decode(String.self)
}
}
}
一个API我处理returns要么:
{
"title": "Hello World"
}
或
{
"title": [{
"text": "Hello World"
}]
}
我的想法是 struct TitleStringValue
有一个自定义解码器,像这样:
struct TitleStringValue: Decodable {
let text: String
struct TitleStringValueInner: Decodable {
let text: String
}
init(from decoder: Decoder) throws {
if let stringContainer = try? decoder.singleValueContainer() {
text = try stringContainer.decode(String.self)
} else {
var arrayContainer = try decoder.unkeyedContainer()
text = try arrayContainer.decode(TitleStringValueInner.self).text
while !arrayContainer.isAtEnd {
_ = try? arrayContainer.decode(TitleStringValueInner.self)
}
}
}
}
struct MyResult: Decodable {
let title: TitleStringValue
}
但是在 title 由数组组成的情况下,TitleStringValue init(from decoder: Decoder)
从未被调用,因为解码器之前失败,遇到一个需要单一值类型的数组。
有办法解决吗?
我可以在我的 MyResult 结构级别上实现解码,但这意味着每个具有 TitleStringValue
s 的结构都需要一个自定义解码器,所以我更愿意在 TitleStringValue 级别上实现它。
我的建议是在这两种情况下都保留 title
属性。
首先尝试解码String
。如果这无法解码 Text
的数组(我保持名称简单)获取第一项并将 text
值分配给 title
.
struct Title: Decodable {
struct Text : Decodable { let text : String }
let title : String
private enum CodingKeys : String, CodingKey { case title }
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
do {
title = try container.decode(String.self, forKey: .title)
} catch DecodingError.typeMismatch {
let textArray = try container.decode([Text].self, forKey: .title)
title = textArray.first?.text ?? ""
}
}
}
这里的问题是 singleValueContainer 也可用于解码数组。因此,您得到的错误是由 TitleStringValue
的 init(from:)
函数内部的第二个 try
产生的,而不是之前的
话虽如此,您可以像这样进一步简化您的自定义解码:
struct TitleStringValue: Decodable {
let text: String
struct TitleStringValueInner: Decodable {
let text: String
}
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let string = try? container.decode([TitleStringValueInner].self).first?.text {
text = string
} else {
text = try container.decode(String.self)
}
}
}