我正在尝试对来自API的数据进行编码和解码,该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"]
在结构中使用自定义的编码/解码方法可以解决此问题,但必须为每个结构/类创建很多样板。
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,并且用户不是我在这里寻找的其他API格式。
答案 0 :(得分:0)
它比singleValueContainer
使用unkeyedContainer
更强大。如果要将数组项分配给struct成员,则无论如何都必须编写一个自定义初始化程序
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])
}
}