如何使用快速可解码协议解析嵌套的JSON数据?

时间:2019-08-12 17:01:17

标签: ios json swift decodable

我有一个从服务器获取一些JSON数据的应用,如下所示:

"operationsInfo": {
    "bill": {
        "activeProviders": [
              {
                "max": 50,
                "min": 10,
                "name": "name1"
              },
              {
                "max": 50,
                "min": 10,
                "name": "name2"
              }
         ]
    },
    "pin": {
        "activeProviders": [
              {
                "max": 50,
                "min": 10,
                "name": "name3"
              },
              {
                "max": 50,
                "min": 10,
                "name": name4
              }
        ]
    }
}

如何使用快速可解码协议反序列化此JSON数据? 我的自定义对象如下:

struct operationList: Decodable {

    let name: String
    let action: String
    let min, max: Int
}

operationList对象中的操作值必须等于“ bill”或“ pin”。最后,我想在解码JSON数据时获得一个operationList对象类型的数组,例如:

  

let operationListArray = [operationList1,operationList2,operationList3,operationList4]   operationList1.action =“ bill”,operationList1.max = 50,operationList1.name =“ name1”   operationList2.action =“ bill”,operationList2.max = 50,operationList2.name =“ name2”   operationList3.action =“ pin”,operationList3.max = 50,operationList3.name =“ name3”   operationList4.action =“ pin”,operationList4.max = 50,operationList4.name =“ name4”

我已经看到其他类似的答案,例如:How to decode a nested JSON struct with Swift Decodable protocol? 但是我的问题是我如何将“ bill”或“ pin”放在操作值中,并且将来可能将新的键值(例如“ transfer”(例如“ pin”或“ bill”)添加到JSON数据中。

1 个答案:

答案 0 :(得分:1)

正如@rmaddy在评论中提到的那样,您要分两个步骤进行操作。

首先,创建一个与您的JSON格式匹配的结构并将其解码:

struct Response: Decodable {
    let operationsInfo: [String: Providers]
}

struct Providers: Decodable {
    let activeProviders: [Provider]
}

struct Provider: Decodable {
    let name: String
    let min: Int
    let max: Int
}

let response = try JSONDecoder().decode(Response.self, from: data)

然后,声明一个结构,该结构表示您希望数据使用的格式并进行映射:

struct ProviderAction {
    let action: String
    let provider: Provider
}

let actions: [ProviderAction] = response.operationsInfo.map { action, providers in
    providers.activeProviders.map { ProviderAction(action: action, provider: $0) }
}.flatMap { $0 }