从NSJSONSerialization初始化带有AnyObject?的Swift类

3

我正在使用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。它可以为你检查所有内容并给你一个嵌套字典。个人而言,我会使用这个来将JSON映射到Swift模型中,使用结构体在init中分配数据,并适当地嵌套结构体,从类似于“Root()”开始向下延伸。 - Cole
@Cole 我知道SwiftyJSON和Argo,但我不想依赖它们。使用Swift模型的struct而不是class可能是个好主意。 - wigging
1个回答

0

因此,如果不使用第三方库,if let树通常是最佳实践,这就是你展示的内容。为了帮助你以后更好地开发,可以将对象层次结构重建为JSON格式,作为Swift中的结构模型。例如:

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?")
}

那个字典将会是你的结构体的输入。


你能详细说明一下使用“结构体”来构建对象层次结构的含义吗? - wigging
你仍在使用第三方库SwiftyJSON。正如我的问题所述,我想避免使用别人的库来解析json。 - wigging
我知道,那只是使用结构体的示例。在它们的初始化器中,您可以按任何方式分配值,我只是使用SwiftyJSON,因为我最初就是这样写的。无论如何,mongoId = json["resultset"]["account"]["mongoId"].string 可以很容易地变成 mongoId = JSONDictionary["resultset"]["account"]["mongoId"] ,其中 let JSONDictionary: Dictionary = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &error) as NSDictionary - Cole
重点是将字典转换为易于阅读和访问的数据。请参阅此链接,了解有关将JSON直接解析为字典的更多信息。https://dev59.com/ZWAf5IYBdhLWcg3wwk4V - Cole
链接中的所有示例也使用了第三方库。我开始觉得在Swift中处理JSON没有简单的方法。 - wigging
我尝试了另一种可能适用于您的方法。请查看我的答案以获取更多详细信息。 - Cole

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接