如何使用Swift 4.0中具有嵌套数组的数组解析JSON?

时间:2017-11-26 21:01:13

标签: arrays json swift

我正在尝试解析JSON API,我试图提取关键值" data"的数字。如您所见,这些图形嵌套在两个数组中,其中第二个数组没有要引用的键值。我该怎么做?

{
"dataset": {
"id": 9789340,
"name": "DCC share price (DCC), Currency GBX",
"description": "Stock Prices for Dcc Share Price (dcc), Currency Gbx from the London Stock Exchange.<br><br>Currency: GBX",
"start_date": "2006-03-16",
"end_date": "2017-11-22",
"column_names": [
  "Date",
  "Price",
  "High",
  "Low",
  "Volume",
  "Last Close",
  "Change",
  "Var%"
],
"data": [
  [
    "2017-11-22",
    7060.0,
    7185.0,
    7045.0,
    156444.0,
    7060.0,
    -95.0,
    -1.33
  ],
  [
    "2017-11-21",
    7155.0,
    7210.0,
    7130.0,
    189002.0,
    7155.0,
    -30.0,
    -0.42
  ],
]
}

到目前为止,我已经做到了这一点。

struct Dataset: Decodable {
let name: String
let description: String
let column_names: [ColumnNames]
let data: [StockData]
}
struct ColumnNames: Decodable {
// What happens here??
}
struct StockData: Decodable {
// What happens here??
}

guard let url = URL(string : jsonUrlString) else
{ return }

URLSession.shared.dataTask(with: url) { (data, response, err) in

guard let jsonData = data else { return }

do{
let dataSet = try JSONDecoder().decode(Dataset.self, from: jsonData)
let dataArray = dataset.data
            dump(dataArray)
for stockDataArray in dataArray {
    for stockItems in stockDataArray
                dump(stockItems)
            }
}

正如您所看到的,我不知道如何解码&#34; StockData&#34;因为JSON数据是一个数组数组。如果我已经回答了这个问题,那么希望我能够解决#34; ColumnNames&#34;应该解析。它也不是具有要解析的键值的字典。

1 个答案:

答案 0 :(得分:1)

这是使用JSONDecoder

强大的自定义功能的解决方案

它会创建合并column_namesdata数组的词典。

这是你的JSON

let jsonString = """
{
    "dataset": {
        "id": 9789340,
        "name": "DCC share price (DCC), Currency GBX",
        "description": "Stock Prices for Dcc Share Price (dcc), Currency Gbx from the London Stock Exchange.<br><br>Currency: GBX",
        "start_date": "2006-03-16",
        "end_date": "2017-11-22",
        "column_names": ["Date", "Price", "High", "Low", "Volume", "Last Close", "Change", "Var%"],
        "data": [["2017-11-22", 7060.0, 7185.0, 7045.0, 156444.0, 7060.0, -95.0, -1.33],
            ["2017-11-21", 7155.0, 7210.0, 7130.0, 189002.0, 7155.0, -30.0, -0.42]]
    }
}
"""

和两个结构,一个用于根对象,一个用于Dataset,在此示例中仅idname被解码,data将包含合并的数组字典

struct Root : Decodable {
    let dataset : Dataset
}

struct Dataset : Decodable {

    private enum CodingKeys : String, CodingKey {
        case id, name, columnNames = "column_names", data
    }

    let id : Int
    let name : String

    var data = [[String:Any]]()

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(Int.self, forKey: .id)
        name = try container.decode(String.self, forKey: .name)
        let columnNames = try container.decode([String].self, forKey: .columnNames)

        var outerContainer = try container.nestedUnkeyedContainer(forKey: .data)
        while !outerContainer.isAtEnd {
            var columnIndex = 0
            var dataSet = [String:Any]()
            var innerContainer = try outerContainer.nestedUnkeyedContainer()
            let date = try innerContainer.decode(String.self)
            var key = columnNames[columnIndex]
            dataSet[key] = date
            columnIndex += 1
            while !innerContainer.isAtEnd {
                let value = try innerContainer.decode(Double.self)
                key = columnNames[columnIndex]
                dataSet[key] = value
                columnIndex += 1
            }
            data.append(dataSet)
        }

    }
}

现在解码这些东西

let data = Data(jsonString.utf8)
do {
    let decoder = JSONDecoder()
    let root = try decoder.decode(Root.self, from: data)
    print(root.dataset)
} catch {
    print("error: ", error)
}