使用解码器快速嵌套JSON时出错 [英] Error in using Decoder swift Nested JSON

查看:56
本文介绍了使用解码器快速嵌套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:

  1. 更改属性名称:

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆