[英]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.