使用解码器快速嵌套JSON时出错 [英] Error in using Decoder swift Nested JSON
问题描述
我想解析来自服务器的JSON获取,但是我有错误,我不知道为什么?! 这是我的结构:
I want to parsing a JSON get from server but I have error i don't know why?!! this is my struct:
struct MyResponse:Decodable {
let cats: [Cats]
}
struct Cats: Decodable {
let id: Int
let name: String
let menu: [Cats]
enum CodingKeys:String, CodingKey {
case name
case id
case menu = "SubMenu"
}
}
并创建此扩展名:
extension MyResponse.Cats {
init(from decoder: Decoder) throws {
let valus = try decoder.container(keyedBy: CodingKeys.self)
name = try valus.decode(String.self, forKey: .name)
id = try valus.decode(Int.self, forKey: .id)
menu = try valus.decodeIfPresent(String.self, forKey: .menu)
}
}
我不知道如何解析此json.这个json非常重要,因为这是商店的类别.这是我的json值:
I don't know how to parse this json. This json is very important because this is category of store of store. and this is my json value :
{
"cats": [
{
"id": 15,
"name": "کسب و کار ها",
"menu": [
{
"id": 16,
"name": "فروشگاهی",
"menu": [
{
"id": 17,
"name": "ورزشی"
},
{
"id": 18,
"name": "نوشت افزار"
}
]
},
{
"id": 19,
"name": "خدماتی",
"menu": ""
}
]
},
也许在将来的菜单中现在没有子菜单 如何处理菜单是否为零或有一些数据?
maybe in future menu now nil have sub menu how to handle if menu is nil or have some data ??
并且此行位于init:
and this line in init :
menu = try valus.decodeIfPresent(String.self, forKey: .menu)
出现此错误:
无法分配类型为'String'的值?键入"[[MyResponse.Cats]""
Cannot assign value of type 'String?' to type '[MyResponse.Cats]'
推荐答案
JSON示例包括一个表示"menu": ""
的条目,而您的结构假定它是另一个Menu
实例null
或完全不存在.
JSON example includes an entry that says "menu": ""
, whereas your structure assumes it is either another Menu
instance, null
, or completely absent.
正如vadian指出的那样,如果您的子菜单有时以""
的形式返回,则您可以编写一个自定义的init(from:)
方法,该方法手动解析JSON,如他所举例说明的那样.但是更好的办法是修复生成该JSON的所有内容,以使"menu":""
根本不存在,或者如果存在,则为"menu":null
(注意,不带引号).最好用JSON修复原始问题,而不是编写麻烦的JSON解析init(from:)
来解决问题.
As vadian pointed out, if your submenus sometimes come back as ""
, you can write a custom init(from:)
method that manually parsed the JSON, as he illustrated. But better would be to fix whatever generated that JSON, so that the "menu":""
was not present at all, or if it was, it would be "menu":null
(note, no quotes). It's better to fix the original problem in the JSON, rather than writing cumbersome JSON parsing init(from:)
to handle the problem.
假设您修复了JSON,那么正如其他人指出的那样,还有另一个问题.您的Menu
结构定义了一个名为submenu
的属性,但您的JSON不使用该键.它使用menu
.因此,您可以:
Assuming you fix the JSON, there is, as others have noted, another problem. Your Menu
structure defines a property called submenu
, but your JSON doesn't use that key. It uses menu
. So, you either can:
-
更改属性名称:
Change the property name:
struct Menu: Codable {
let name: String
let id: Int
let menu: [Menu]?
}
或
使用CodingKeys
枚举:
struct Menu: Codable {
let name: String
let id: Int
let submenu: [Menu]?
enum CodingKeys: String, CodingKey {
case name, id
case submenu = "menu"
}
}
或
更改JSON以使用submenu
键.
Change the JSON to use submenu
key.
假设您修复了JSON,这表明您可以轻松地解析它.这使用上面显示的方法2:
Assuming you fix the JSON, this demonstrates that you can parse it quite easily. This uses approach 2, shown above:
let data = """
{
"cats": [
{
"id": 15,
"name": "کسب و کار ها",
"menu": [
{
"id": 16,
"name": "فروشگاهی",
"menu": [
{
"id": 17,
"name": "ورزشی"
},
{
"id": 18,
"name": "نوشت افزار"
}
]
},
{
"id": 19,
"name": "خدماتی"
}
]
}
]
}
""".data(using: .utf8)!
struct Respons: Codable {
let cats: [Menu]
}
struct Menu: Codable {
let name: String
let id: Int
let submenu: [Menu]?
enum CodingKeys: String, CodingKey {
case name, id
case submenu = "menu"
}
}
do {
let object = try JSONDecoder().decode(Respons.self, from: data)
print(object)
} catch {
print(error)
}
这篇关于使用解码器快速嵌套JSON时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!