【问题标题】:What is the best way to convert JSON into swift object, Checking keys and values both将 JSON 转换为 swift 对象的最佳方法是什么,同时检查键和值
【发布时间】:2023-04-02 07:24:02
【问题描述】:

好吧,我认为这不是一个大问题,但我错了。目前我正在做一个项目,我得到了大量的 JSON 回报。我正在取那些并制作我的模型。现在在我的模型中,我正在通过 guard 语句检查是否有任何值为 nil 的值。这是我的模型示例:

import Foundation
import SwiftyJSON

class profileModel {

var _phone_no: String?
var _full_name: String?
var _image: String?
var _email: String?
var _profile_pic: String?
var _rating: Int?
var _dob: String?
var _gender: String?
var _firstName: String?
var _lastName: String?


required init?(phone_no: String, full_name: String, image: String, email: String, profile_pic: String, rating: Int, dob: String, gender: String, firstName: String, lastName: String) {
    self._phone_no = phone_no
    self._full_name = full_name
    self._image = image
    self._email = email
    self._profile_pic = profile_pic
    self._rating = rating
    self._dob = dob
    self._gender = gender
    self._firstName = firstName
    self._lastName = lastName
}

convenience init?(json: JSON){

  guard let phone_no = json["phone_no"].string,
        let full_name = json["full_name"].string,
        let image = json["profile_pic"].string,
        let email = json["email"].string,
        let profile_pic = json["profile_pic"].string,
        let rating = json["rating"].int,
        let dob = json["dob"].string,
        let gender = json["gender"].string,
        let firstName = json["first_name"].string,
        let lastName = json["last_name"].string else {
        print("Profile Detail Model Error")
        return nil
    }

    self.init(phone_no: phone_no, full_name: full_name, image: image, email: email, profile_pic: profile_pic, rating: rating, dob: dob, gender: gender, firstName: firstName, lastName: lastName)

  }

}

但是,当 JSON 返回中缺少任何 key 时,如何防止崩溃?似乎当我同时检查 keyvalues 时,班级变得非常大,必须有更好的方法。

【问题讨论】:

  • 只要您使用的是SwiftyJSON,这不再是您担心的理由。看看this 部分。
  • 不相关但非常糟糕的方法是带有前导下划线的属性(这不是 Objective-C)、snake_cased 变量名称、实际上不会失败的可失败初始化程序,因为所有传递的值都是非可选的并且示意性地声明所有属性作为可选的 don't care 不在场证明(再次强调,这不是 Objective-C)。

标签: ios json swift


【解决方案1】:

将属性设为可选项是一种好方法,但是您可以利用 Swift 4 中的新 Codable,您可以将 JSON 解析为任何符合 Codable 的数据模型。

在您的情况下,您可以这样编写模型:

class ProfileModel: Codable {
    var phone_no: String?
    var full_name: String?
    var profile_pic: String?
    var email: String?
//    var profile_pic: String?
    var rating: String?
    var dob: String?
    var gender: String?
    var first_name: String?
    var last_name: String?
}

当您需要从服务器解码时使用:

let profile = try JSONDecoder().decode(ProfileModel.self, from: json1)

如果你得到一个“配置文件”数组,只需将上面的行更改为:

let profiles = try JSONDecoder().decode([ProfileModel].self, from: json1)

不再需要使用 SwiftyJSON 库了。

【讨论】:

  • 使属性成为可选项是一种好方法 - 真的吗?!!并导致它在任何地方使用可选绑定可选链接。根本不是一个好主意!您将推断出 strictly / strongly 类型语言(显然是 Swift)的哪些优势?
【解决方案2】:

您应该查看Codable 协议:以下 Playground 显示了当您尝试解析缺少特定键的 Json 时会发生什么。

//: Playground - noun: a place where people can play

import Foundation

首先,我们创建我们的 ProfileModel 类并模拟一个相关的 json。

class ProfileModel: Codable {

    //...
    var _firstName: String?
    var _lastName: String?

}

let profile = ProfileModel()
profile._firstName = "Hans"
profile._lastName = "Peter"
let json = try! JSONEncoder().encode(profile)

解析按预期工作:

do {
    let profileAgain = try JSONDecoder().decode(ProfileModel.self, from: json)
    print(profileAgain._firstName) // "Optional("Hans")\n"
    print(profileAgain._lastName) // "Optional("Peter")\n"
} catch {
    print("something went wrong")
}

那么,当我们将另一个属性添加到我们的类 (_phone_no) 时,会发生什么,该属性不包含在我们的 Json 中?如果这个新属性是可选的,则没有什么真正改变:

class AnotherProfileModel: Codable {

    //...
    var _firstName: String?
    var _lastName: String?
    var _phone_no: Int?
}

do {
    let anotherProfile = try JSONDecoder().decode(AnotherProfileModel.self, from: json)
    print(anotherProfile._firstName) // "Optional("Hans")\n"
    print(anotherProfile._lastName) // "Optional("Peter")\n"
    print(anotherProfile._phone_no) // "nil\n"
} catch {
    print("something went wrong")
}

但是如果这个属性不是可选的,解码器会抛出错误:

class AndYetAnotherProfileModel: Codable {

    //...
    var _firstName: String?
    var _lastName: String?
    var _phone_no: Int
}

do {
    let andYetAnotherProfileModel = try JSONDecoder().decode(AndYetAnotherProfileModel.self, from: json)
} catch {
    print("something went wrong") // "something went wrong\n"
}

我希望这个工作示例能帮助您更好地理解Codable 协议:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    相关资源
    最近更新 更多