尝试解码动态 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)")
        }
    }