【问题标题】:Initialize Swift class with AnyObject? from NSJSONSerialization用 AnyObject 初始化 Swift 类?来自 NSJSONSerialization
【发布时间】:2015-10-10 08:24:50
【问题描述】:

我在 Swift 1.2 中使用 NSJSONSerialization 来解析从 API 响应返回的一些 json。

var err: NSError?
let opts = NSJSONReadingOptions.AllowFragments
let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(jsonData!, options: opts, error: &err)

解析后的 json 以AnyObject? 的形式提供。我想用这个可选来初始化一个类对象,它可以用作应用程序中的模型数据。

class Alerts {
    let type: String
    let date: String
    let description: String
    let expires: String
    let message: String

    init(json: AnyObject) {
        if let
        jsonDict = json as? [String: AnyObject],
        alertsArray = jsonDict["alerts"] as? [AnyObject],
        alertsDict = alertsArray[0] as? [String: AnyObject],
        type = alertsDict["type"] as? String,
        date = alertsDict["date"] as? String,
        description = alertsDict["description"] as? String,
        expires = alertsDict["expires"] as? String,
        message = alertsDict["message"] as? String
        {
            self.type = type
            self.date = date
            self.description = description
            self.expires = expires
            self.message = message
        }
        else
        {
            self.type = "err"
            self.date = "err"
            self.description = "err"
            self.expires = "err"
            self.message = "err"
        }
    }
}

// example of creating a data model from the json
let alerts = Alerts(json: json!)
alerts.type
alerts.date
alerts.description
alerts.expires
alerts.message

由于NSJSONSerialization 返回一个可选值,因此我必须在提取 json 数据时检查每个值类型是否存在。正如您在上面的代码中看到的,我使用 Swift 1.2 中改进的可选绑定来清理 init 方法。在不使用第三方库的情况下,我还能对类模型(enumsstructstype aliases)做些什么来使其更具可读性?我应该为模型数据使用struct 而不是class?是否可以使用enumstruct 创建自定义类型来表示json 对象?

【问题讨论】:

  • 我知道你提到你不想使用第三方库,但我真的认为你应该看看 SwiftyJSON。它会为您检查所有内容并为您提供嵌套字典。就个人而言,然后我会使用它来使用 Structs 将 JSON 映射到一个 swift 模型,在 init 中分配数据并嵌套 Structs,从诸如“Root()”之类的东西开始,然后从那里向下。
  • @Cole 我知道 SwiftyJSON 和 Argo,但我不想依赖它们。不过,为 swift 模型使用 struct 而不是 class 可能是个好主意。

标签: json swift enums optional nsjsonserialization


【解决方案1】:

因此,在不使用第三方库的情况下,if let 树通常是您所展示的最佳实践。为了在以后帮助您,也许可以在 JSON 中将您的对象层次结构重新创建为 Swift 中的 Struct 模型。比如:

var json = JSON(JSONData.sharedjson.jsonRaw!)
var mongoIdTest = json["resultset"]["account"]["mongoId"].string

struct Root {
    var timestamp: Int?
    var resultset = ResultSet()

    init() {
        self.timestamp = json["timestamp"].int
        println(json)
    }

}

struct ResultSet {
    var alert: String?

    var account = Account()
    var customer = Customer()

    init() {

    }


}

struct Account {
    var mongoId: String?

    init() {
        mongoId = json["resultset"]["account"]["mongoId"].string
    }
}

struct Locations {

}

struct Customer {
    var account: String?
    var address: String?
    var id: String?
    var loginId: String?
    var mongoId: String?
    var name: String?

    var opco = Opco()

    init() {
        account = json["resultset"]["customer"]["account"].string
        address = json["resultset"]["customer"]["address"].string
        id = json["resultset"]["customer"]["id"].string
        loginId = json["resultset"]["customer"]["loginId"].string
        mongoId = json["resultset"]["customer"]["mongoId"].string
        name = json["resultset"]["customer"]["name"].string
    }

}

struct Opco {
    var id: String?
    var phone: String?
    var cutOffTime: String?
    var name: String?
    var payerId: String?

    init() {
        id = json["resultset"]["customer"]["opco"]["id"].string
        phone = json["resultset"]["customer"]["opco"]["phone"].string
        cutOffTime = json["resultset"]["customer"]["opco"]["cutOffTime"].string
        name = json["resultset"]["customer"]["opco"]["name"].string
        payerId = json["resultset"]["customer"]["opco"]["payerId"].string
    }
}

这样,您仍然可以使用自动完成和点符号来浏览您的层次结构。

编辑:我有一个来自我从事的实际项目的数据结构添加到答案中,希望这能提供一个更好的主意。请记住,我使用 SwiftyJSON 进行 JSON() 调用。

编辑 2:

这是我发现的一种无需使用其他库即可将 JSON 信息放入 Swift 字典的方法。我不确定是否有另一种方法可以在不使用第三方库的情况下更轻松。

var urlToRequest = "https://EXAMPLE.com/api/account.login?username=MY_USERNAME&password=Hunter2"

if let json = NSData(contentsOfURL: NSURL(string: urlToRequest)!) {

    // Parse JSON to Dictionary
    var error: NSError?
    let boardsDictionary = NSJSONSerialization.JSONObjectWithData(json, options: NSJSONReadingOptions.MutableContainers, error: &error) as? Dictionary<String, AnyObject>
    fulljson = boardsDictionary

    // Display all keys and values
    println("Keys in User Data:")
    for (key, value) in boardsDictionary! {
        println("\(key)-------\(value)")
    }

    println(fulljson?["resultset"])
}
else {
    println("Test JSON nil: No Connection?")
}

该字典将成为您的 Structs 的输入。

【讨论】:

  • 能否详细说明您对对象层次结构使用struct 的含义?
  • 您仍在使用第三方库 SwiftyJSON。正如我的问题所述,我想避免使用别人的库来解析 json。
  • 我知道,这只是使用结构的一个示例。在他们的初始化器中,你可以以任何你想要的方式赋值,我只是使用了 SwiftyJSON,因为这就是我最初编写它的方式。无论如何,mongoId = json["resultset"]["account"]["mongoId"].string 很容易成为mongoId = JSONDictionary["resultset"]["account"]["mongoId"] 其中let JSONDictionary: Dictionary = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &amp;error) as NSDictionary
  • 关键是将字典变成易于阅读和访问的数据。有关将 JSON 直接解析为字典的更多信息,请参阅此链接。 stackoverflow.com/questions/24310324/…
  • 链接中的所有示例也都使用了第三方库。我开始认为在 Swift 中处理 json 没有简单的方法。
猜你喜欢
  • 1970-01-01
  • 2020-02-09
  • 2019-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 2016-04-11
相关资源
最近更新 更多