解析复杂 JSON 数组的有效方法
Posted
技术标签:
【中文标题】解析复杂 JSON 数组的有效方法【英文标题】:Efficient way to parse through complex JSON array 【发布时间】:2015-12-20 18:12:08 【问题描述】:我从 Yandex 收到以下 JSON 响应:
"def" : [
"pos" : "adverb",
"text" : "ganz",
"tr" : [
"pos" : "noun",
"text" : "whole",
"mean" : [
"text" : "gesamte"
]
,
"syn" : [
"pos" : "adverb",
"text" : "totally"
,
"pos" : "adverb",
"text" : "really"
,
"pos" : "adverb",
"text" : "absolutely"
],
"mean" : [
"text" : "ziemlich"
,
"text" : "völlig"
,
"text" : "wirklich"
,
"text" : "absolut"
],
"pos" : "adverb",
"text" : "quite"
,
"pos" : "adjective",
"text" : "very",
"mean" : [
"text" : "sehr"
]
,
"syn" : [
"pos" : "adverb",
"text" : "perfectly"
],
"mean" : [
"text" : "vollständig"
,
"text" : "vollkommen"
],
"pos" : "adverb",
"text" : "fully"
,
"pos" : "noun",
"text" : "altogether",
"mean" : [
"text" : "insgesamt"
]
]
,
"pos" : "adjective",
"text" : "ganz",
"tr" : [
"pos" : "verb",
"text" : "complete",
"mean" : [
"text" : "vollständig"
]
]
],
"head" :
我想把它巧妙地解析成这种格式:
struct Definition
var pos: String
var text: String
var translations: [Translation]
var examples: [Example]
struct Translation
var pos: String
var text: String
var synonyms: [Synonym]
var meanings: [Meaning]
struct Synonym
var pos: String
var text: String
struct Meaning
var text: String
struct Example
但是,我不知道如何巧妙地做到这一点。目前我只是嵌套了大量的 for 循环:
if let value = response.result.value
let json = JSON(value)["def"]
for (key, subJson) in json
for (key, subJson) in subJson
print(key)
print(subJson)
它很难看,可读性也不是很好。我正在使用SwiftyJSON
。有没有一种简单的方法来解析我缺少的这个 JSON(它是数组和字典的混合体)?
谢谢
编辑:明确地说,我想要一个适用于所有响应的解决方案,而不仅仅是给定的示例
【问题讨论】:
【参考方案1】:解析 JSON 并没有更聪明的方法来做到这一点。后端使结构像这样,因为它是有意义的。所以,加油吧。
顺便说一句,它的结构有点复杂。在 Swift 中,总是建议使用类型注解。否则,如果你使用推理,编译器会疯狂地试图找出你的类型。编译时间会加起来。
【讨论】:
【参考方案2】:为了减轻硬编码的痛苦(至少一点点),您可以将解码的角色分配给每个结构。
每个结构都有一个 init(_ dictionary:)
初始化器,它接收一个 JSON 字典,该字典将其键映射到属性。
在下面的示例中,我设置了所有可选属性,因为我不知道这些 JSON 名称是否存在于每个响应中。但是您可以将它们设为非可选并设置一个默认值,如var pos = ""
,如果您确定值类型不能更改,在init(dictionary:)
中,您可以像pos = value as! String
一样强制向下转换它们或使用条件如果您不确定,请垂头丧气if let string = value as? String pos = string
。
struct Definition
var pos: String?
var text: String?
var translations: [Translation]?
extension Definition
init(_ dictionary: [String: AnyObject])
for (key, value) in dictionary
switch key
case "pos": pos = value as? String
case "text": text = value as? String
case "tr":
if let trs = value as? [[String: AnyObject]]
translations = [Translation]()
for tr in trs
let translation = Translation(tr)
translations?.append(translation)
default: break
struct Translation
var pos: String?
var text: String?
var synonyms: [Synonym]?
var meanings: [Meaning]?
extension Translation
init(_ dictionary: [String: AnyObject])
for (key, value) in dictionary
switch key
case "pos": pos = value as? String
case "text": text = value as? String
case "syn":
if let syns = value as? [[String: AnyObject]]
synonyms = [Synonym]()
for syn in syns
let synonym = Synonym(syn)
synonyms?.append(synonym)
case "mean":
if let means = value as? [[String: AnyObject]]
meanings = [Meaning]()
for mean in means
let meaning = Meaning(mean)
meanings?.append(meaning)
default: break
struct Synonym
var pos: String?
var text: String?
extension Synonym
init(_ dictionary: [String: AnyObject])
for (key, value) in dictionary
switch key
case "pos": pos = value as? String
case "text": text = value as? String
default: break
struct Meaning
var text: String?
extension Meaning
init(_ dictionary: [String: AnyObject])
for (key, value) in dictionary
switch key
case "text": text = value as? String
default: break
当你处理响应时:
if let value = response.result.value
let json = JSON(value)
let dict = json.dictionaryObject! // convert to native dictionary
var definitions = [Definition]()
for def in dict["def"] as! [[String: AnyObject]]
let definition = Definition(def)
definitions.append(definition)
请注意,我使用本机字典只是为了使代码更通用。
【讨论】:
【参考方案3】:您可以按如下方式简单地访问您的嵌套数据
let jsonDict = JSON(data: response.2!)
let someValue = String(jsonDict["firstDict"][0]["secondDict"]["thirdDict"][0]["fourthDict"])
希望有帮助
【讨论】:
谢谢,我一直在使用 Json 查看器。我可能不清楚,但我想要一个适用于所有响应(不仅仅是这个)的解决方案,所以手动指责这样的嵌套数据并没有真正的帮助。 @DanilvanderMerwe 我不知道所有回复的意思。当您从给定的 API 解析 JSON 时,您必须事先了解其结构才能编写解析器。 API 不会更改其 JSON 响应的结构,否则,它们就不是 API,而且您不是在解析,而是在编写可以说是更复杂的东西,称为刮板。 我很乐意提供进一步帮助,但您的问题表述不当(我在 JSON 中的任何地方都看不到examples
),并且数据显然是相关数据,您的数据模型。您在这里问的问题不止 1 个:1-如何使用 SwiftyJSON(我向您展示)解析我的 JSON,2-如何将其放入结构中,以及 3-您隐含地问,我如何关联单个结构相互表示一个对象
使用类型注解,否则编译器会为了判断类型而发疯。以上是关于解析复杂 JSON 数组的有效方法的主要内容,如果未能解决你的问题,请参考以下文章