当对象包含其他对象数组时如何解析 JSON?
Posted
技术标签:
【中文标题】当对象包含其他对象数组时如何解析 JSON?【英文标题】:How to parse JSON when the object contains an array of other objects? 【发布时间】:2016-11-02 13:46:22 【问题描述】:我一直在尝试在 Swift 中解析 JSON,其中对象包含其他对象的数组。像这样:
"people": [
"name": "Life Sciences",
"id": "4343435",
"children" : [
"name": "name1",
"id" : "5344444",
,
"name": "name2",
"id" : "5134343",
,
.....
我需要能够访问 name 和 id 属性,但我似乎无法弄清楚我在下面的代码中做错了什么。我的 JSON 文件包含所有必要的数据,但是,当我尝试循环遍历子数组时,我不断收到 “unexpectedly found nil when unwrapping optional” 错误。在该行之前,JSON 被正确解析并正常工作。
let loadURL = "https:// ....."
var people = [Person]()
func getPersonData()
let request = URLRequest(url: URL(string: loadURL)!)
let urlSession = URLSession.shared
let task = urlSession.dataTask(with: request, completionHandler: (data, response, error) -> Void in
if let error = error
print(error)
return
// Parse JSON data
if let data = data
self.people = self.parseJsonData(data)
OperationQueue.main.addOperation() -> Void in
self.tableView.reloadData()
)
task.resume()
func parseJsonData(_ data: Data) -> [Person]
var people = [Person]()
do
let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
// Parse JSON data
let jsonPeople = jsonResult?["people"] as! [AnyObject]
for jsonPerson in jsonPeople
let person = Person()
person.name = jsonPerson["name"] as! String
person.id = jsonPerson["id"] as! String
//ERROR//: "unexpectedly found nil when unwrapping optional..."
let jsonChildren = jsonResult?["children"] as! [AnyObject]
for jsonChild in jsonChildren
let child = Child()
child.name = jsonEntrance["name"] as! String
child.age = jsonEntrance["age"] as! Int
person.children.append(child)
people.append(person)
catch
print(error)
return people
【问题讨论】:
【参考方案1】:你在这里犯了一个错误:
let jsonChildren = jsonResult?["children"] as! [AnyObject]
应该是:
let jsonChildren = jsonPerson["children"] as! [AnyObject]
【讨论】:
【参考方案2】:可能,您的 JSON 数据在某些时候没有“子”值,请尽量避免强制转换为 [AnyObject]。您可以尝试以这种方式更改它:
if let result = jsonResult, let jsonChildren = result["children"] as? [AnyObject]
for jsonChild in jsonChildren
let child = Child()
child.name = jsonEntrance["name"] as! String
child.age = jsonEntrance["age"] as! Int
person.children.append(child)
另外,您可以尝试使用SwiftyJSON,这将帮助您更轻松地进行 json 数据处理。
【讨论】:
【参考方案3】:您的代码看起来不错,但问题是您正在搜索错误的字典。您的“jsonResult”键没有“儿童”键。但是你的 'jsonPerson' 对象有一个 'children' 键。替换下面的代码行 -
let jsonChildren = jsonResult?["children"] as! [AnyObject]
用这一行替换这一行 -
let jsonChildren = jsonPerson?["children"] as! [AnyObject]
【讨论】:
【参考方案4】:首先,JSON 并不代表代码中的实际 JSON。
其次,永远不要在 Swift 中使用 NSDictionary
,除非你别无选择。
第三,将包含字典的 JSON 数组转换为 [[String:Any]]
,而不是 [Any(Object)]
第四,Swift 3 中的 JSON 字典是 [String:Any]
第五,使用可选绑定来避免运行时错误(崩溃)
func parseJsonData(_ data: Data) -> [Person]
var people = [Person]()
do
let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:Any]
// Parse JSON data
if let jsonPeople = jsonResult["people"] as? [[String:Any]]
for jsonPerson in jsonPeople
let person = Person()
person.name = jsonPerson["name"] as! String
person.id = jsonPerson["id"] as! String
// children is a key of a person not of the root object !
if let jsonChildren = jsonPerson["children"] as? [[String:Any]]
for jsonChild in jsonChildren
let child = Child()
child.name = jsonChild["name"] as! String
child.age = jsonChild["age"] as! Int
person.children.append(child)
people.append(person)
catch
print(error)
return people
PS:您将收到另一个错误未定义标识符,因为您的代码中的子循环中的jsonEntrance
不存在并且children
是people
的键而不是根对象的键。
【讨论】:
以上是关于当对象包含其他对象数组时如何解析 JSON?的主要内容,如果未能解决你的问题,请参考以下文章
如何解析包含多个相同类型的 JSON 对象(不是数组)的 JSON 对象
如何使用 Newtonsoft.Json 将包含数组数组的 json 对象解析为 C# 中的对象列表?
使用 Node.js 解析不包含 JSON 对象的 JSON 数组