如何使用 Swift Decodable 解码嵌套的 JSON 结构?

问题描述

这是我的 JSON

{
    "myItems": {
        "item1name": [{
            "url": "google.com","isMobile": true,"webIdString": "572392"
        },{
            "url": "hulu.com","isMobile": false,"webIdString": "sad1228"
        }],"item2name": [{
            "url": "apple.com","webIdString": "dsy38ds"
        },{
            "url": "Facebook.com","webIdString": "326dsigd1"
        },{
            "url": "YouTube.com","webIdString": "sd3dsg4k"
        }]
    }
}

json 可以有多个项目(例如 item1name、item2name、item3name,...),每个项目可以有多个对象(示例中第一个项目有 2 个对象,第二个项目有 3 个对象)。

>

这是我想要保存的结构(不完整):

struct ServerResponse: Decodable {
    let items: [MyItem]?
}

struct MyItem: Decodable {
    let itemName: String?
    let url: String?
    let isMobile: Bool?
    let webIdString: String?
}

在上面的例子中,这意味着 items 列表应该有五个 MyItem 对象。例如,这些将是 MyItem 对象:

#1: 项目名称:项目1名称, 网址:google.com, isMobile:真实, webIdString:572392

#2: 项目名称:项目1名称, 网址:hulu.com, isMobile:假, webIdString:sad1228

#3: 项目名称:项目2名称, 网址:apple.com, isMobile:真实, webIdString: dsy38ds

#4: 项目名称:项目2名称, 网址:Facebook.com, isMobile:真实, webIdString: 326dsigd1

#5: 项目名称:项目2名称, 网址:YouTube.com, isMobile:真实, webIdString: sd3dsg4k

使用 Decodable 对我来说最好的方法是什么?任何帮助,将不胜感激。我认为这可能类似于这个问题:How to decode a nested JSON struct with Swift Decodable protocol?

解决方法

使用以下代码根据您的要求解码嵌套的 JSON:

import Foundation

// MARK: - Websites
struct Websites: Codable {
    var myItems: MyItems
}

// MARK: - MyItems
struct MyItems: Codable {
    var item1Name,item2Name: [ItemName]
    enum CodingKeys: String,CodingKey {
        case item1Name = "item1name"
        case item2Name = "item2name"
    }
}

// MARK: - ItemName
struct ItemName: Codable {
    var url: String
    var isMobile: Bool
    var webIDString: String
    enum CodingKeys: String,CodingKey {
        case url,isMobile
        case webIDString = "webIdString"
    }
}

注意:根据需要更改变量的名称。

编辑

如果您仍然遇到问题,请使用此应用将您的 JSON 转换为 Struct:

Quick Type

,

这是您所追求的结构:

struct Websites: Decodable {
    let items: [Item]

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: Key.self)
        items = try container.decode([String: [Item]].self,forKey: .myItems).values.flatMap { $0 }
    }

    private enum Key: String,CodingKey {
        case myItems
    }
}

struct Item: Decodable {
    let url: String
    let isMobile: Bool
    let webIdString: String
}