试图使用可编码的方法编写一个简单的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:“字符”,intValue: nil),_JSONKey(stringValue:“Index0”,intValue: 0),debugDescription:“期望解码字典,但找到一个数组”,underlyingError: 0)。
在这条线上:
let weaponsContainer = try container.nestedContainer(keyedBy: Weapon.CodingKeys.self, forKey: .weapons)我不知道问题是什么,因为我清楚地(在我看来)要求一批武器,但它认为我无论如何都在找字典。
想知道是否有人对我错过了什么有任何洞察力。
发布于 2018-04-23 05:07:54
只有当您想将子字典或子数组解码为父结构时才需要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) }发布于 2018-04-23 05:08:30
用以下方式替换您的结构:不需要任何自定义初始化器
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)发布于 2018-04-23 05:17:03
尝尝这个
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
}https://stackoverflow.com/questions/49973573
复制相似问题