【问题标题】:How to parse an inner field in a nested JSON object如何解析嵌套 JSON 对象中的内部字段
【发布时间】:2012-11-27 21:36:38
【问题描述】:

我有一个类似于这个的 JSON 对象:

{
  "name": "Cain",
  "parents": {
    "mother" : "Eve",
    "father" : "Adam"
  }
}

现在我想将“name”和“mother”解析到这个结构中:

struct {
  Name String
  Mother String `json:"???"`
}

我想用json:... struct 标签指定JSON 字段名称,但是我不知道用什么作为标签,因为它不是我感兴趣的顶级对象。我在encoding/json 包文档或流行的博客文章 JSON and Go。我还测试了motherparents/motherparents.mother

【问题讨论】:

    标签: json go


    【解决方案1】:

    只要传入的数据不太动态,就可以使用结构。

    http://play.golang.org/p/bUZ8l6WgvL

    package main
    
    import (
        "fmt"
        "encoding/json"
        )
    
    type User struct {
        Name string
        Parents struct {
            Mother string
            Father string
        }
    }
    
    func main() {
        encoded := `{
            "name": "Cain",
            "parents": {
                "mother": "Eve",
                "father": "Adam"
            }
        }`
    
        // Decode the json object
        u := &User{}
        err := json.Unmarshal([]byte(encoded), &u)
        if err != nil {
            panic(err)
        }
    
        // Print out mother and father
        fmt.Printf("Mother: %s\n", u.Parents.Mother)
        fmt.Printf("Father: %s\n", u.Parents.Father)
    }
    

    【讨论】:

    • 我也知道这一点。但是我不想使用两个结构,而是一个,也不想嵌套它们。结构字段标签提供了一种指定应该使用哪个 JSON 字段的方法,但我很好奇它们是否提供了一种访问嵌套字段的方法,即不是根对象成员的字段。
    • remy_o#go-nuts 上说,encoding/json 包不能满足我的要求,所以这是我坚持的答案。或者用他的话来说:“json 包不是 XPath”。
    【解决方案2】:

    不幸的是,与encoding/xml 不同,json 包不提供访问嵌套值的方法。您需要创建一个单独的父母结构或将类型分配为map[string]string。例如:

    type Person struct {
        Name string
        Parents map[string]string
    }
    

    然后你可以为母亲提供一个吸气剂:

    func (p *Person) Mother() string {
        return p.Parents["mother"]
    }
    

    这可能会或可能不会在您当前的代码库中发挥作用,并且如果将Mother 字段重构为方法调用不在菜单上,那么您可能需要创建一个单独的方法来解码并符合您当前的结构。

    【讨论】:

      【解决方案3】:

      这是我在 Go Playground 中快速编写的一些代码

      http://play.golang.org/p/PiWwpUbBqt

      package main
      
      import (
          "fmt"
          "encoding/json"
          )
      
      func main() {
          encoded := `{
              "name": "Cain",
              "parents": {
                  "mother": "Eve"
                  "father": "Adam"
              }
          }`
      
          // Decode the json object
          var j map[string]interface{}
          err := json.Unmarshal([]byte(encoded), &j)
          if err != nil {
              panic(err)
          }
      
          // pull out the parents object
          parents := j["parents"].(map[string]interface{})
      
          // Print out mother and father
          fmt.Printf("Mother: %s\n", parents["mother"].(string))
          fmt.Printf("Father: %s\n", parents["father"].(string))
      }
      

      可能有更好的方法。我期待看到其他答案。 :-)

      【讨论】:

      • 我知道这是可行的,但我希望有一个更...可读的解决方案。
      • 它必须以这种方式工作,因为 interface{} 必须被断言为一个类型(在这种情况下,类型 map[string]interface{})。更简单的方法是使用带有帮助方法的库,例如 go-simplejson
      • 这种解组嵌套结构让我非常头疼。嘘
      【解决方案4】:

      最近,gjson 支持选择嵌套的 JSON 属性。

      name := gjson.Get(json, "name")
      mother := gjson.Get(json, "parents.mother")
      

      【讨论】:

        【解决方案5】:

        如何使用上面建议的中间结构进行解析,然后将相关值放入“真实”结构中?

        import (
            "fmt"
            "encoding/json"
            )
        
        type MyObject struct{
          Name string
          Mother string
        }
        
        type MyParseObj struct{
           Name string
           Parents struct {
                 Mother string
                 Father string
           } 
        }
        
        
        func main() {
            encoded := `{
                 "name": "Cain",
                 "parents": {
                     "mother": "Eve",
                     "father": "Adam"
                 }
            }`
        
            pj := &MyParseObj{}
            if err := json.Unmarshal([]byte(encoded), pj); err != nil {
                return
            }
            final := &MyObject{Name: pj.Name, Mother: pj.Parents.Mother}
            fmt.Println(final)  
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-08
          • 1970-01-01
          • 2021-12-23
          • 2016-01-01
          相关资源
          最近更新 更多