如何解码多个类型的嵌套数组?

时间:2019-08-12 09:17:02

标签: json swift decodable

这是我的JSON

{  
  "response":[  
    [  
      { 
        "neededValue" : "Something I really need"
      },

      567890812309,
      "Some text. Bla bla bla",

      {
        "Garbage" : "Garbage I do not need"
      }
    ]
  ]
}

它包含一个带有两个字典的数组,一个Int和一个String。我需要解码第一本字典。我尝试过:

struct response: Decodable {
     var response: [[String : String]]
}

但是,这显然不能捕获String值和Int值。如何描述数组?请帮忙。

1 个答案:

答案 0 :(得分:1)

import Foundation

let str = """
{
    "response":
    [
        [
            {
                "neededValue" : "Something I really need"
            },
            567890812309,
            "Some text. Bla bla bla",
            {
                "Garbage" : "Garbage I don't need"
            }
        ]
    ]
}
"""


let data = str.data(using: .utf8)!

struct NeededValue: Decodable {
    let neededValue: String
}
struct Garbage: Decodable {
    let garbage = ""
    enum CodingKeys: String, CodingKey {
        case garbage = "Garbage"
    }
}

struct Response: Decodable {

    let neededValue: NeededValue
    let intValue: Int
    let stringValue: String
    let garbageValue: Garbage

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()

        neededValue = try container.decode(NeededValue.self)
        intValue = try container.decode(Int.self)
        stringValue = try container.decode(String.self)
        garbageValue = try container.decode(Garbage.self)
    }
}

struct Container: Decodable {

    let response: [Response]

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        response = try container.decode([Response].self, forKey: .response)
    }

    enum CodingKeys: String, CodingKey {
        case response
    }
}

do {
    let res = try JSONDecoder().decode(Container.self, from: data)
    print(res)
} catch {
    print(error)
}

顺便说一句,使用此链接stackoverflow.com/a/47215561/5555803可以改善答案,更好的方法是:

struct Response: Decodable {

    var value: Any?

    init(from decoder: Decoder) throws {
        if let int = try? Int(from: decoder) {
            value = int
        } else if let string = try? String(from: decoder) {
            value = string
        } else if let neededValue = try? NeededValue(from: decoder) {
            value = neededValue
        } else if let garbage = try? Garbage(from: decoder) {
            value = garbage
        }
    }
}

struct ResponseChild: Decodable {
    var response: [[Response]]?
}

do {
    let res = try JSONDecoder().decode(ResponseChild.self, from: data)
    print(res)
} catch {
    print(error)
}