2012-11-27 28 views
35

我有类似下面这样的JSON对象:如何解析Golang中嵌套的JSON对象的内部字段?

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

现在我想分析“名”和“母亲”这个结构:

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

我想指定的JSON字段名与json:...结构标记,但我不知道如何使用作为标记,因为它不是我感兴趣的顶级对象。在encoding/json程序包文档中,也没有在热门博客文章JSON and Go中发现此内容。我也测试了mother,parents/motherparents.mother

回答

16

不幸的是,不像encoding/xmljson包不提供一种方法来访问嵌套的值。您需要创建一个单独的Parents结构或将该类型指定为map[string]string。例如:

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

然后,您可以为母亲一个getter像这样:

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

这可能会或可能不会发挥到当前的代码库,如果重构的Mother领域的一个方法调用不在菜单上,那么你可能想要创建一个单独的方法来解码和符合你当前的结构。

6

下面是一些代码我烤了真正的快速中转到游乐场

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

有可能是一个更好的办法。我期待着看到其他答案。 :-)

+0

我知道这有效,但我希望有一个更可读的解决方案。 – keks

+0

它必须以这种方式工作,因为interface {}必须被声明为一个类型(在这种情况下,请键入map [string] interface {})。更简单的方法是使用带有辅助方法的库,例如[go-simplejson](http://godoc.org/github.com/bitly/go-simplejson) – Druska

+0

这样解组嵌套的结构给我带来了严重的麻烦。 boooo –

17

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

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) 
} 
+1

我也意识到这一点。不过,我不想使用两个结构,但不想嵌套它们。 Struct字段标记给出了一种方法来指定应该使用哪个JSON字段,但我很好奇他们是否提供了访问嵌套字段的方法,这些字段不是根对象的成员。 – keks

+1

在'#go-nuts'上说'remy_o','encoding/json'包不能满足我的要求,所以这是我坚持的答案。或者用他的话说:“json软件包不是XPath”。 – keks

2

如何使用一个中间结构作为上面提出的用于解析的中间结构,然后将相关值放入“真实”结构中?

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) 
} 
3

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

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