尝试解码动态 JSON 响应
Trying to decode dynamic JSON response
我正在尝试解码来自 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]
类型的字典。
如果将字典的每个条目的键和值输入到 Tag
对象中,则可以按 name
对标签数组进行排序。或者您可以先对字典键进行排序,两者都有效。
Catch:只有 如果 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 { [=11=].key < .key })
var tags = [Tag]()
// Iterate over a sorted array of keys
decoded.compactMap { [=11=].key }.sorted().forEach {
// Create the Tag
tags.append(Tag(name: [=11=], count: decoded[[=11=]] ?? 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 { [=12=].key < .key })
var tags = [Tag]()
// Iterate over the dictionary entries
decoded.forEach {
// Create the Tag
tags.append(Tag(name: [=12=].key, count: [=12=].value))
}
// Sort the array by name
tags = tags.sorted { [=12=].name < .name }
print(tags)
} catch {
print("Oops: something went wrong while decoding, \(error.localizedDescription)")
}
}
我正在尝试解码来自 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]
类型的字典。
如果将字典的每个条目的键和值输入到 Tag
对象中,则可以按 name
对标签数组进行排序。或者您可以先对字典键进行排序,两者都有效。
Catch:只有 如果 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 { [=11=].key < .key })
var tags = [Tag]()
// Iterate over a sorted array of keys
decoded.compactMap { [=11=].key }.sorted().forEach {
// Create the Tag
tags.append(Tag(name: [=11=], count: decoded[[=11=]] ?? 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 { [=12=].key < .key })
var tags = [Tag]()
// Iterate over the dictionary entries
decoded.forEach {
// Create the Tag
tags.append(Tag(name: [=12=].key, count: [=12=].value))
}
// Sort the array by name
tags = tags.sorted { [=12=].name < .name }
print(tags)
} catch {
print("Oops: something went wrong while decoding, \(error.localizedDescription)")
}
}