簡體   English   中英

使用可解碼的 Swift 從混合數組中解析 JSON

[英]Parse JSON from mixed array with Decodable Swift

JSON link https://raw.githubusercontent.com/shimuldn/Todoey/master/file.json

JSON 代碼

{
"report": [
     [
        {
           "name": "Delhi"
         },
        63,
        7
      ]
   ]
}

我的代碼

struct ApiData: Codable {
    let report: [[Details]]
}
struct Details: Codable {
    let name: String
}

我想訪問值 decodeData.report[0][0].name

一旦我運行代碼

debugDescription: "Expected to decode Dictionary<String, Any> but found a number instead.", underlyingError: nil

當我刪除

let name: String

沒有錯誤。

我想從鍵“名稱”和值 63 中獲取值

首先,我假設這是您想要的數據結構。 如果不是,請使用您預期的輸出數據結構更新問題。 report[0][0].name在 Swift 中使用起來很脆弱且笨拙。創建一個與您想要的數據相匹配的結構。然后解碼為該結構。)

struct ApiData: Decodable {
    let report: [Details]
}

struct Details {
    let name: String
    let value1: Int
    let value2: Int
}

所以每個 Details 都有一個名稱對象和兩個整數值。 報告是詳細信息列表。

鑒於此,您可以使用unkeyedContainer手動解碼 Details。 要取出 name 字段,可以很方便地創建一個輔助結構:

extension Details: Decodable {
    struct NameField: Decodable {
        let name: String
    }

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        self.name = try container.decode(NameField.self).name
        self.value1 = try container.decode(Int.self)
        self.value2 = try container.decode(Int.self)
    }
}

你的評論指出“名字下面還有一些。” 在這種情況下,您可能需要一個對象而不是一個字符串。 在這種情況下,它看起來像這樣:

struct Person: Decodable {
    let name: String
}

struct Details {
    let person: Person
    let value1: Int
    let value2: Int
}

extension Details: Decodable {

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        self.person = try container.decode(Person.self)
        self.value1 = try container.decode(Int.self)
        self.value2 = try container.decode(Int.self)
    }
}

最后,值列表可能是無界的,而您需要一個數組:

struct Details {
    let person: Person
    let values: [Int]
}

在這種情況下,您可以通過從unkeyedContainer提取所有值來進行unkeyedContainer

extension Details: Decodable {    
    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        self.person = try container.decode(Person.self)
        var values: [Int] = []
        while !container.isAtEnd {
            values.append(try container.decode(Int.self))
        }
        self.values = values
    }
}

有很多方法可以解決這個問題。 這完全取決於您希望如何使用數據,以及數據具有多少結構。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM