我正试图解码来自Pinboard API的所有标签的JSON响应。我有一个简单的模型,我想解码成:
struct Tag: Coddle, Hashable {
let name: String
let count: Int
}
问题是,我得到的JSON响应是完全动态的,像这样:
{
"tag_name_1": 5,
"tag_name_2": 5,
"tag_name_3": 5,
}
所以使用JSONDecoder.decode([Tag].self, data)
解码到我的模型总是失败。
您的JSON可以被解码为[String: Int]
类型的字典。
如果将字典中每个条目的key和value输入到Tag
对象中,则可以按name
对标签数组进行排序。或者可以先对字典键进行排序,两种方法都可以。
Catch:only,如果JSON的顺序也是键的顺序。如果JSON像这样到达,它将不遵循顺序,例如:
{
"tag_name_3": 5,
"tag_name_2": 5,
"tag_name_1": 5,
}
下面是代码(有两个选项):
// First way:
// 1) Decode the dictionary
// 2) Sort the dictionary keys
// 3) Iterate, creating a new Tag and appending it to the array
private func decode1() {
let json = "{ "tag_name_1": 5, "tag_name_2": 5, "tag_name_3": 5}"
let data = json.data(using: .utf8)
do {
// Decode into a dictionary
let decoded = try JSONDecoder().decode([String: Int].self, from: data!)
print(decoded.sorted { $0.key < $1.key })
var tags = [Tag]()
// Iterate over a sorted array of keys
decoded.compactMap { $0.key }.sorted().forEach {
// Create the Tag
tags.append(Tag(name: $0, count: decoded[$0] ?? 0))
}
print(tags)
} catch {
print("Oops: something went wrong while decoding, (error.localizedDescription)")
}
}
// Second way:
// 1) Decode the dictionary
// 2) Create the Tag objects
// 3) Sort the array by Tag.name
private func decode2() {
let json = "{ "tag_name_1": 5, "tag_name_2": 5, "tag_name_3": 5}"
let data = json.data(using: .utf8)
do {
// Decode into a dictionary
let decoded = try JSONDecoder().decode([String: Int].self, from: data!)
print(decoded.sorted { $0.key < $1.key })
var tags = [Tag]()
// Iterate over the dictionary entries
decoded.forEach {
// Create the Tag
tags.append(Tag(name: $0.key, count: $0.value))
}
// Sort the array by name
tags = tags.sorted { $0.name < $1.name }
print(tags)
} catch {
print("Oops: something went wrong while decoding, (error.localizedDescription)")
}
}