codableKey中的keyNotFound用于JSON响应

问题描述 投票:0回答:2

Json响应解析为可编码的字符串,以发现错误的KeyNotFound。可编码到包装器类时为KeyNotFound

    Unexpected error: keyNotFound(CodingKeys(stringValue: "id", intValue: nil), 
Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil)], 
debugDescription: "No value associated with key CodingKeys(stringValue: \"id\", intValue: nil)
 (\"id\").", underlyingError: nil)).

响应数据

{
    "msg": {
        "success": [
            ""
        ]
    },
    "data": {
        "jobs": {
            "current_page": 1,
            "data": [
                {
                    "id": 154,
                    "user": "UserName"}
]
}
}
}

服务电话

let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
    if let error = error {
        print("error: \(error)")
    } else {
        if let response = response as? HTTPURLResponse {
            print("statusCode: \(response.statusCode)")
        }
        if let data = data, let dataString = String(data: data, encoding: .utf8) {
            let jsonData = dataString.data(using: .utf8)!

            do {
                let jsonDecoder = JSONDecoder()
                let user = try jsonDecoder.decode(JobListModel.self, from: data)
                print("Hello \(user.msg )")
            } catch {
                print("Unexpected error: \(error).")
            }
        }
    }
}

ModelClass。

struct JobListModel: Codable {

    let msg: Msg
    let data: Data

    private enum CodingKeys: String, CodingKey {
        case msg = "msg"
        case data = "data"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        msg = try values.decode(Msg.self, forKey: .msg)
        data = try values.decode(Data.self, forKey: .data)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(msg, forKey: .msg)
        try container.encode(data, forKey: .data)
    }

}
ios swift codable
2个回答
0
投票

这是因为您的解码模型不正确。使用以下模型:

struct JobListModel: Codable {
    let msg: Msg
    let data: JobListData
}

struct JobListData: Codable {
    let jobs: Jobs
}

struct Jobs: Codable {
    let currentPage: Int
    let data: [JobData]

    enum CodingKeys: String, CodingKey {
        case currentPage = "current_page"
        case data
    }
}

struct JobData: Codable {
    let id: Int
    let user: String
}

struct Msg: Codable {
    let success: [String]
}

0
投票

原因:

在模型中,您将Data用作JSON响应中data键的类型。

Data是预定义的类型,这就是解析时引发错误的原因。

解决方案:

您需要将其修改为某些自定义类型,例如。 JobListData。因此,您的[Codable模型应该像,

struct JobListModel: Codable {
    let msg: Msg
    let data: JobListData
}

struct JobListData: Codable {
    let jobs: Jobs
}

struct Jobs: Codable {
    let currentPage: Int
    let data: [JobsData]
}

struct JobsData: Codable {
    let id: Int
    let user: String
}

struct Msg: Codable {
    let success: [String]
}

您现在可以像这样解析data

do {
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let response = try decoder.decode(JobListModel.self, from: data)
    print(response)
} catch {
    print(error)
}

在上面的代码中,我将convertFromSnakeCase用作decoder's keyDecodingStrategy。这样,您可以避免显式定义enum CodingKeys仅用于处理json响应中的snake-case keys

注:当没有特定于解析的内容时,请不要明确写出init(from:)encode(to:)的定义。假设您正确设计了模型,Codable中的直接解析将由编译器自动处理。

© www.soinside.com 2019 - 2024. All rights reserved.