Swift 对表示为数组的对象的可编码支持
Swift Codable support for objects represented as array
我正在尝试对 API 中的数据进行编码和解码,将对象表示为字符串数组,例如:
[
["username", "message", "date"],
["username", "message", "date"],
["username", "message", "date"]
]
这是对应的 Codable 结构:
struct Message: Codable {
let user: String
let content: String
let date: String
private enum CodingKeys: Int, CodingKey {
case user = 0
case content = 1
case date = 2
}
}
编码和解码都不起作用;编码显示创建的是 JSON 对象而不是数组:
let msg = Message(user: "foo", content: "content", date: "2019-06-04")
let jsonData = try! JSONEncoder().encode(msg)
let jsonString = String(data: jsonData, encoding: .utf8)!
最后的字符串是:
{"content":"content","user":"foo","date":"2019-06-04"}
我的目标是获取下面的字符串
["foo", "content", "2019-06-04"]
在结构中使用自定义 encode/decode 方法解决了这个问题,但强制为每个 struct/class.
创建大量样板文件
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let values = try container.decode([String].self)
user = values[CodingKeys.user.rawValue]
content = values[CodingKeys.content.rawValue]
date = values[CodingKeys.date.rawValue]
}
如何为任何对象继续支持这一点?
是的,这是一个奇怪的 API,但这不是我第一次遇到其中的一个,并且用户使用不同的 API 格式不是我在这里寻找的。
而不是 singleValueContainer
使用 unkeyedContainer
,它更健壮。如果要将数组项分配给结构成员,则无论如何都必须编写自定义初始化程序
struct Message: Codable {
let user: String
let content: String
let date: String
init(from decoder: Decoder) throws {
var arrayContainer = try decoder.unkeyedContainer()
guard arrayContainer.count == 3 else { throw DecodingError.dataCorruptedError(in: arrayContainer, debugDescription: "The array must contain three items") }
user = try arrayContainer.decode(String.self)
content = try arrayContainer.decode(String.self)
date = try arrayContainer.decode(String.self)
}
func encode(to encoder: Encoder) throws {
var arrayContainer = encoder.unkeyedContainer()
try arrayContainer.encode(contentsOf: [user, content, date])
}
}
我正在尝试对 API 中的数据进行编码和解码,将对象表示为字符串数组,例如:
[
["username", "message", "date"],
["username", "message", "date"],
["username", "message", "date"]
]
这是对应的 Codable 结构:
struct Message: Codable {
let user: String
let content: String
let date: String
private enum CodingKeys: Int, CodingKey {
case user = 0
case content = 1
case date = 2
}
}
编码和解码都不起作用;编码显示创建的是 JSON 对象而不是数组:
let msg = Message(user: "foo", content: "content", date: "2019-06-04")
let jsonData = try! JSONEncoder().encode(msg)
let jsonString = String(data: jsonData, encoding: .utf8)!
最后的字符串是:
{"content":"content","user":"foo","date":"2019-06-04"}
我的目标是获取下面的字符串
["foo", "content", "2019-06-04"]
在结构中使用自定义 encode/decode 方法解决了这个问题,但强制为每个 struct/class.
创建大量样板文件init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let values = try container.decode([String].self)
user = values[CodingKeys.user.rawValue]
content = values[CodingKeys.content.rawValue]
date = values[CodingKeys.date.rawValue]
}
如何为任何对象继续支持这一点?
是的,这是一个奇怪的 API,但这不是我第一次遇到其中的一个,并且用户使用不同的 API 格式不是我在这里寻找的。
而不是 singleValueContainer
使用 unkeyedContainer
,它更健壮。如果要将数组项分配给结构成员,则无论如何都必须编写自定义初始化程序
struct Message: Codable {
let user: String
let content: String
let date: String
init(from decoder: Decoder) throws {
var arrayContainer = try decoder.unkeyedContainer()
guard arrayContainer.count == 3 else { throw DecodingError.dataCorruptedError(in: arrayContainer, debugDescription: "The array must contain three items") }
user = try arrayContainer.decode(String.self)
content = try arrayContainer.decode(String.self)
date = try arrayContainer.decode(String.self)
}
func encode(to encoder: Encoder) throws {
var arrayContainer = encoder.unkeyedContainer()
try arrayContainer.encode(contentsOf: [user, content, date])
}
}