如何使用 Codable 从字典中解码 .key

Posted

技术标签:

【中文标题】如何使用 Codable 从字典中解码 .key【英文标题】:How to decode .keys from dictionary using Coadable 【发布时间】:2018-11-14 14:13:33 【问题描述】:

我有以下 JSON 响应。我想使用 .keys 方法获取“数据”的所有键,即 [“rules”、“preference”、“goals”]。但我无法使用 .keys 功能获得所有键的数组。我也附上了我的代码 sn-p。如果您遇到过这个问题,请建议我摆脱这种担忧。

虽然,我可以使用 ObjectMapper 和本机 Dictionary 对象获取这些 allKey。我只需要知道为什么我无法使用 Codable 实现这一目标。

我的 json 响应


    "statusCode": 200,
    "status": "success",
    "message": null,
    "data": 
        "rules": 
            "goals": 
                "min": "1",
                "max": "3"
            
        ,
        "preference": [
            1,
            2,
            3
        ],
        "goals": 
            "total": 4,

            "data": []
        
    

我的代码片段:

struct MeetingsDataModal: Codable 
    let statusCode: Int?
    let status: String?
    let message: String?
    let data: Results?
    enum CodingKeys: String, CodingKey 
        case statusCode = "statusCode"
        case status = "status"
        case message = "message"
        case data = "data"
    
    func allkeys() 

    


struct Results : Codable 
    let rules: Rules?
    let preference: [Preference]?
    let goals: Goals?
    enum CodingKeys: String, CodingKey 
        case rules = "rules"
        case preference = "preference"
        case goals = "goals"
    


struct Rules : Codable 

struct Preference : Codable 

struct Goals : Codable 

我的期望

let content = try JSONDecoder().decode(MeetingsDataModal.self, from: (response as? Data)!)
print(content.data.keys)

但我明白了,

“结果?”类型的值没有成员“密钥”

【问题讨论】:

如果有keys,你为什么会期待? Resultsrulesgoalspreferences,就是这样。 @luk2302 感谢您的回复。我需要获取这些 allKeys 并将其显示在表格视图的部分。其余的数组值,我需要在表格视图的行上显示。 allKeys 应该是什么?您的 JSON 和映射结构都没有这样的东西。实际预期输出是多少? 是的。我的预期输出是[“规则”、“偏好”、“目标”]。我可以在 objectMapper 中获取这些方法(.keys)。 知道Decodable 创建的是结构,而不是字典 【参考方案1】:

也许我不太了解这个问题,但您的“密钥”是由您的 Codable 协议定义的 - 所以它们是已知的。如果您使用的是 Swift 4.2+,则可以利用 CaseIterable 协议

struct Results: Codable 
    let testOne: Int
    let testTwo: String
    enum CodingKeys: String, CodingKey, CaseIterable 
        case testOne
        case testTwo
    


Results.CodingKeys.allCases.map  $0.rawValue 

【讨论】:

【参考方案2】:

如果您确实需要 .keys。可以添加两行代码:

   struct Results : Codable 
        let rules: Rules?
        let preference: [Preference]?
        let goals: Goals?
        enum CodingKeys: String, CodingKey 
            case rules = "rules"
            case preference = "preference"
            case goals = "goals"
        

        var keys : [String]
            return["rules", "preference","goals"]
        
    

其实,如果你不喜欢编码/解码方式,我们还有一个传统的 JSON 对象可以帮你处理非结构化的 JSON。

    let obj =   try JSONSerialization.jsonObject(with: response!, options: JSONSerialization.ReadingOptions.allowFragments)

    print((((obj as! [String: Any?])["data"]) as! [String: Any?]).keys)

这是解码数据结构的一种方法。

           let d = """
        
            "statusCode": 200,
            "status": "success",
            "message": null,
            "data": 
                "rules": 
                    "goals": 
                        "min": "1",
                        "max": "3"
                    
                ,
                "preference": [
                1,
                2,
                3
                ],
                "goals": 
                    "total": 4,

                    "data": []
                
            
        
        """.data(using: .utf8)!


        struct MeetingsDataModal: Decodable 
            let statusCode: Int
            let status: String
            let message: String?
            let data: Results
        

        struct Results : Decodable 
            let rules: Rules
            let preference: [Int]
            let goals: Goals
        

        struct Rules : Decodable 
            let goals : DirectData
        
        struct DirectData : Decodable
            let min : String
            let max : String
        
        struct Goals : Decodable 
            let total : Int
            let data : [String]
        

        let data0 = try JSONDecoder().decode(MeetingsDataModal.self, from: d)
        print(data0)

【讨论】:

以上是关于如何使用 Codable 从字典中解码 .key的主要内容,如果未能解决你的问题,请参考以下文章

解码子时嵌套 Codable 结构中父结构的访问属性

如何使用 Codable 解码具有更改键的 json 响应?

Swift Codable - 如何编码和解码字符串化的 JSON 值?

在 swift 中对动态键和动态对象使用 Codable

同时从 API 调用和模型文件中解码 Codable 结构

使用 Codable 解码 JSON,然后填充我的 SwiftUI