簡體   English   中英

Swift 4.1 Decodable 無法使用nestedContainer 解碼嵌套數組

[英]Swift 4.1 Decodable Can't decode nested array with nestedContainer

嘗試使用 Codable 編寫一個簡單的Swift 4.1來解析json

我有一個這樣的struct

struct GameCharacter : Codable {
  var name : String
  var weapons : [Weapon]
  enum CodingKeys : String, CodingKey {
    case name
    case weapons
  }

  init(from decoder: Decoder) {
    do {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try container.decode(String.self, forKey: .name)
        let weaponsContainer = try container.nestedContainer(keyedBy: Weapon.CodingKeys.self, forKey: .weapons)
        self.weapons = try weaponsContainer.decode([Weapon].self, forKey: .weapons)

    } catch let error {
        print("error: \(error)")
        fatalError("error is \(error)")
    }
  }
}

另一個像這樣:

struct Weapon : Codable {    
  var name : String
  enum CodingKeys : String, CodingKey {
    case name
  }

  init(from decoder: Decoder) {
    do {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try container.decode(String.self, forKey: .name)
    } catch let error {
        print("error: \(error)")
        fatalError("error is \(error)")
    }
  }
}

我也有這樣的包裝器struct

struct Game : Codable {
  var characters : [GameCharacter]
  enum CodingKeys : String, CodingKey { case characters }
}

json 數據如下所示:

{ 
  "characters" : [{
    "name" : "Steve",
    "weapons" : [{
      "name" : "toothpick"
    }]
  }]
}

但是,我總是收到 typeMismatcherror 錯誤:

錯誤: typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "characters", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Expected to解碼字典,但找到了一個數組。”,underlyingError: nil))

在這一行:

let weaponsContainer = try container.nestedContainer(keyedBy: Weapon.CodingKeys.self, forKey: .weapons)

我不確定問題是什么,因為我顯然(在我看來)要求一系列武器,但它認為我無論如何都在尋找字典。

想知道是否有人對我缺少的東西有任何見解。

僅當您想將子字典或子數組解碼到父結構中時才需要nestedContainers - 例如將weapons對象解碼到Game結構中 - 情況並非如此,因為您聲明了所有嵌套結構。

要解碼 JSON,您可以省略所有 CodingKeys 和初始值設定項,利用Codable的魔力,這就足夠了:

struct Game : Codable {
    let characters : [GameCharacter]
}

struct GameCharacter : Codable {
    let name : String
    let weapons : [Weapon]
}

struct Weapon : Codable {
    let name : String
}

並稱之為

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

將您的結構替換為不需要任何自定義初始值設定項

import Foundation

struct Weapon: Codable {
    let characters: [Character]
}

struct Character: Codable {
    let name: String
    let weapons: [WeaponElement]
}

struct WeaponElement: Codable {
    let name: String
}

並創造

extension Weapon {
init(data: Data) throws {
    self = try JSONDecoder().decode(Weapon.self, from: data)
}

現在只是

 let weapon = try Weapon(json)

試試這個

let string = """
{
"characters" : [{
    "name" : "Steve",
    "weapons" : [{
    "name" : "toothpick"
        }]
    }]
}
"""

struct GameCharacter: Codable {
    let characters: [Character]
}

struct Character: Codable {
    let name: String
    let weapons: [Weapon]
}

struct Weapon: Codable {
    let name: String
}

let jsonData = string.data(using: .utf8)!
let decodr = JSONDecoder()

let result = try! decodr.decode(GameCharacter.self, from: jsonData)

let weapon = result.characters.flatMap {$0.weapons}

for weaponname in weapon {
    print(weaponname.name) //Output toothpick
}

我有同樣的問題, JSONDecoder()只解碼我的 JSON 的第一級,然后我通過從Codable擴展的類的主體中注釋這些方法來解決這個問題

public class Response<T:Codable> : Codable {

    public let data : T?

//commented this two function and my problem Solved <3
//    enum CodingKeys: String, CodingKey {
//        case data
//    }
//    required public init(from decoder: Decoder) throws {
//        data = try T(from: decoder)
//    }


}

暫無
暫無

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

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