【问题标题】:Decode json output to a model将 json 输出解码为模型
【发布时间】:2018-06-28 09:52:08
【问题描述】:

我想使用 Codable 解析这个 json 输出:

{
"success": true,
"total": 1,
"users": [
    {
        "user": {
            "id": "1",
            "fname": "admin",
            "lname": "admin",
            "login": "admin",
            "actif": "0",
            "last_connection_date": "2018-01-18 16:02:34"
        }
    }
],
"msg": ""
}

我只是想从中提取用户的信息。 我的用户模型

import RealmSwift

class User: Object, Codable {

@objc dynamic var id: String = ""
@objc dynamic var fname: String = ""
@objc dynamic var lname: String = ""
@objc dynamic var login: String = ""

//    private enum CodingKeys : String, CodingKey {
//        case id = "users[0].user.id"
//        case fname = "users[0].user.fname"
//        case lname = "users[0].lname"
//        case login = "users[0].user.login"
//        case password = "users[0].user.password"
//    }

}

// Somewhere in my code
Alamofire.request(Path.userInformations(id: userId).rawValue).
responseJSON(completionHandler: { response in
       do {
            let user = try JSONDecoder().decode(User.self, from: response.data!)
            } catch (let error) {
                print(error.localizedDescription)
            }
       })

我已尝试提取用户的对象,但未能成功将其转换为 Data 以将其提供给 JSONDecoder().decode() 方法。

回应 Vishal16 的评论

我已经尝试过你的第一种方法。它似乎不起作用,因为我认为用户对象之前的关键字“用户”。我尝试添加一个包装用户对象的新结构,但没有解决它。

struct ResponseBody : Codable {
   var success : Bool?
   var total : Int?
   var users : [UserHolder]?
   var msg : String?
   var query_start : String?
   var query_end : String?
   var query_time : String?
   var paging : Bool?
}

struct UserHolder : Codable {
    var user: User?

    enum CodingKeys: String, CodingKey {

        case user = "user"

    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        user = try values.decodeIfPresent(User.self, forKey: .user)
    }
}

【问题讨论】:

  • 将需要更多的上下文。你能分享一下JSONDecoder().decode()这一行的代码吗?
  • @Malik 我已经更新了我的初始帖子,提供了更多上下文(一个简单的 Alamofire 获取请求)
  • error.localizedDescription中打印什么
  • 根据您提供的信息,您的JSON 中的user 容器向下两层。但是在您的代码中,您将完整的 json 传递给期望 json 仅具有 user 容器的解码器
  • @UmairAamir The data couldn’t be read because it is missing

标签: json swift swift4 codable


【解决方案1】:

我认为你的响应类结构应该是这样的:

import Foundation
struct ResponseBody : Codable {
var status : Bool?
var total : Int?
var users : [User]? //list of users 
var msg : String?

enum CodingKeys: String, CodingKey {

    case status = "status"
    case total = "total"
    case users = "users"
    case msg = "msg"
}

init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    status = try values.decodeIfPresent(Bool.self, forKey: . status)
    total = try values.decodeIfPresent(Int.self, forKey: . total)
    users = try values.decodeIfPresent([User].self, forKey: . users)
    msg = try values.decodeIfPresent(String.self, forKey: . msg)
}
}

现在您可以将 JSON 数据检索到对象

let jsonDecoder = JSONDecoder()
let response = try jsonDecoder.decode(ResponseBody.self, from: data)

for user in response.users {
   // user object is here
}

#edit

如果您不想解析对 JSON 对象的完整响应

  1. 首先使用将数据转换为 JSON 对象

    让 jsonResponse = 试试 JSONSerialization.jsonObject(with: data, options: .mutableContainers) as!字典

  2. 获取用户列表字符串 JSON 然后将其转换为数据,然后将数据转换为用户列表对象

    如果让 responseBody = jsonResponse["users"] {

    让 dataBody = (responseBody as!String).data(使用: .utf8)! 如果让 obj = Utils.convertToArray(data: dataBody) { print(obj) // 用户 obj 列表 } }

Hear 是上述实现中使用的方法

class func convertToArray(data: Data) -> [AnyObject]? {
    do {
        return try JSONSerialization.jsonObject(with: data, options: []) as? [AnyObject]
    } catch {
        Constants.print(items: error.localizedDescription)
    }
    return nil
}

希望这对您有所帮助。快乐编码:)

所以听听是适合你的工作代码 它在我的操场上运行良好。请看下面的截图

1.

2.

3.

将 json 输出解码为模型

结果:

【讨论】:

  • 请在最初的帖子中播下我的回复:)
  • 好的,请稍等。
  • 问题是,我有int 而不是string 作为用户ID ?。感谢您的宝贵时间!
【解决方案2】:
class User: Object, Codable {

@objc dynamic var id: String = ""
@objc dynamic var fname: String = ""
@objc dynamic var lname: String = ""
@objc dynamic var login: String = ""

}

class Users: Object, Codable {

@objc dynamic var users: [User]

}

用于解码

let user = try JSONDecoder().decode(Users.self, from: response.data!)

我认为它应该可以解决问题。

另一种方法是,您必须将response.data 转换为Dictionary 才能挖掘到user 对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-23
    • 2011-10-26
    • 1970-01-01
    相关资源
    最近更新 更多