解析复杂 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 数组的有效方法的主要内容,如果未能解决你的问题,请参考以下文章

关于解析各种复杂json

在 Pig 中解析复杂的 JSON 字符串

在颤动中用数组解析复杂的JSON

将 swift 数组解析为有效的 json

android使用gson解析嵌套复杂的json数据,数据怎么显示到布局上,布局怎么写

安卓怎么用gson解析服务端返回的复杂json数据