如何使用Coadable

时间:2018-11-14 14:13:34

标签: ios json decode codable swift4.2

我有一个下面的JSON响应。我想使用.keys方法获取“数据”的所有关键字,即“规则”,“首选项”,“目标”]。但是我无法使用.keys功能获得所有键的数组。我也附上了我的代码段。如果您曾经遇到过这种情况,请建议我摆脱这种担忧。

尽管如此,我可以使用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)

但是我得到了,

  

“结果”类型的值没有成员“键”

2 个答案:

答案 0 :(得分: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 }

答案 1 :(得分:0)

如果确实需要.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)