2012-11-27 27 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")