从数组初始化的可解码
Decodable that inits from an array
我有一个 JSON 对象数组。简化后,它具有以下形式:
[
{"name": "Tinky Winky"},
{"name": "Dipsy"},
{"name": "Laa-Laa"},
{"name": "Po"}
]
我可以创建一个结构 Tubby
可以解码数组中的单个实例:
struct Tubby: Codable {
let name: String
}
我想创建一个可以从 JSON:
数组解码的结构体 Tubbies
struct Tubbies: Codable {
let tubbies: [Tubby]
init(from decoder: Decoder) throws {
// What goes here?
tubbies = ???
}
…但现在我不知道应该如何解码?我只想做:
init(from decoder: Decoder) throws {
// What goes here?
tubbies = decoder.decode([Tubby].self)
}
但是 Decoder
不提供 decode
。它有:
/// Returns the data stored in this decoder as represented in a container
/// keyed by the given key type.
///
/// - parameter type: The key type to use for the container.
/// - returns: A keyed decoding container view into this decoder.
/// - throws: `DecodingError.typeMismatch` if the encountered stored value is
/// not a keyed container.
func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey
/// Returns the data stored in this decoder as represented in a container
/// appropriate for holding values with no keys.
///
/// - returns: An unkeyed container view into this decoder.
/// - throws: `DecodingError.typeMismatch` if the encountered stored value is
/// not an unkeyed container.
func unkeyedContainer() throws -> UnkeyedDecodingContainer
/// Returns the data stored in this decoder as represented in a container
/// appropriate for holding a single primitive value.
///
/// - returns: A single value container view into this decoder.
/// - throws: `DecodingError.typeMismatch` if the encountered stored value is
/// not a single value container.
func singleValueContainer() throws -> SingleValueDecodingContainer
singleValueContainer
(这是一个错误,正如答案所阐明的——谢谢!)和 unkeyedContainer
都抛出数组并显示一条消息表明他们不支持数组。我可以使用 container(keyedBy:)
吗?我应该传递什么作为密钥?
我认为这不是一个好方法,因为 [Tubby].self
很简单,可以在任何地方使用。
但是如果你只是想将数组包装在另一种类型中,你应该有这样的东西:
详细版本:
struct Tubbies: Codable {
let tubbies: [Tubby]
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.tubbies = try container.decode([Tubby].self)
}
}
较短的版本:
struct Tubbies: Codable {
let tubbies: [Tubby]
init(from decoder: Decoder) throws {
tubbies = try [Tubby](from: decoder)
}
}
用法:
let tubbies: Tubbies = try! JSONDecoder().decode(Tubbies.self, from: jsonData)
我有一个 JSON 对象数组。简化后,它具有以下形式:
[
{"name": "Tinky Winky"},
{"name": "Dipsy"},
{"name": "Laa-Laa"},
{"name": "Po"}
]
我可以创建一个结构 Tubby
可以解码数组中的单个实例:
struct Tubby: Codable {
let name: String
}
我想创建一个可以从 JSON:
数组解码的结构体Tubbies
struct Tubbies: Codable {
let tubbies: [Tubby]
init(from decoder: Decoder) throws {
// What goes here?
tubbies = ???
}
…但现在我不知道应该如何解码?我只想做:
init(from decoder: Decoder) throws {
// What goes here?
tubbies = decoder.decode([Tubby].self)
}
但是 Decoder
不提供 decode
。它有:
/// Returns the data stored in this decoder as represented in a container
/// keyed by the given key type.
///
/// - parameter type: The key type to use for the container.
/// - returns: A keyed decoding container view into this decoder.
/// - throws: `DecodingError.typeMismatch` if the encountered stored value is
/// not a keyed container.
func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey
/// Returns the data stored in this decoder as represented in a container
/// appropriate for holding values with no keys.
///
/// - returns: An unkeyed container view into this decoder.
/// - throws: `DecodingError.typeMismatch` if the encountered stored value is
/// not an unkeyed container.
func unkeyedContainer() throws -> UnkeyedDecodingContainer
/// Returns the data stored in this decoder as represented in a container
/// appropriate for holding a single primitive value.
///
/// - returns: A single value container view into this decoder.
/// - throws: `DecodingError.typeMismatch` if the encountered stored value is
/// not a single value container.
func singleValueContainer() throws -> SingleValueDecodingContainer
(这是一个错误,正如答案所阐明的——谢谢!)和 singleValueContainer
unkeyedContainer
都抛出数组并显示一条消息表明他们不支持数组。我可以使用 container(keyedBy:)
吗?我应该传递什么作为密钥?
我认为这不是一个好方法,因为 [Tubby].self
很简单,可以在任何地方使用。
但是如果你只是想将数组包装在另一种类型中,你应该有这样的东西:
详细版本:
struct Tubbies: Codable {
let tubbies: [Tubby]
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.tubbies = try container.decode([Tubby].self)
}
}
较短的版本:
struct Tubbies: Codable {
let tubbies: [Tubby]
init(from decoder: Decoder) throws {
tubbies = try [Tubby](from: decoder)
}
}
用法:
let tubbies: Tubbies = try! JSONDecoder().decode(Tubbies.self, from: jsonData)