在Golang中解组嵌套的JSON对象

关于这个话题 有 几个 问题 ,但是他们都没有涉及我的案子,因此我正在创build一个新的问题。

我有以下JSON:

{"foo":{ "bar": "1", "baz": "2" }, "more": "text"} 

有没有一种方法来解组嵌套bar属性,并将其直接分配给一个struct属性而不创build一个嵌套的结构?

我现在采用的解决scheme如下:

 type Foo struct { More String `json:"more"` Foo struct { Bar string `json:"bar"` Baz string `json:"baz"` } `json:"foo"` // FooBar string `json:"foo.bar"` } 

这是一个简化的版本,请忽略冗长。 正如你所看到的,我希望能够parsing和赋值

 // FooBar string `json:"foo.bar"` 

我见过有人用地图,但那不是我的情况。 我基本上不关心foo (这是一个大对象)的内容,除了一些特定的元素。

在这种情况下,正确的做法是什么? 我不是在寻找怪异的黑客,因此,如果这是要走的路,我很好。

有没有一种方法来解组嵌套bar属性,并将其直接分配给一个struct属性而不创build一个嵌套的结构?

不,encoding / json不能像“> some> deep> childnode”那样使用encoding / xml。 嵌套结构是要走的路。

像Volker所说的那样,嵌套结构是要走的路。 但是如果你真的不想嵌套的结构,你可以重写UnmarshalJSON函数。

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

 type A struct { FooBar string // takes foo.bar FooBaz string // takes foo.baz More string `json:"more"` } func (a *A) UnmarshalJSON(b []byte) error { var f interface{} json.Unmarshal(b, &f) m := f.(map[string]interface{}) foomap := m["foo"] v := foomap.(map[string]interface{}) a.FooBar = v["bar"].(string) a.FooBaz = v["baz"].(string) return nil } 

请忽略我没有返回适当的错误的事实。 为了简单起见,我把它留下了。

这是一个如何解除来自Safebrowsing v4 API sbserver代理服务器的JSON响应的示例: https : //play.golang.org/p/4rGB5da0Lt

 // this example shows how to unmarshall JSON requests from the Safebrowsing v4 sbserver package main import ( "fmt" "log" "encoding/json" ) // response from sbserver POST request type Results struct { Matches []Match } // nested within sbserver response type Match struct { ThreatType string PlatformType string ThreatEntryType string Threat struct { URL string } } func main() { fmt.Println("Hello, playground") // sample POST request // curl -X POST -H 'Content-Type: application/json' // -d '{"threatInfo": {"threatEntries": [{"url": "http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/"}]}}' // http://127.0.0.1:8080/v4/threatMatches:find // sample JSON response jsonResponse := `{"matches":[{"threatType":"MALWARE","platformType":"ANY_PLATFORM","threatEntryType":"URL","threat":{"url":"http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/"}}]}` res := &Results{} err := json.Unmarshal([]byte(jsonResponse), res) if(err!=nil) { log.Fatal(err) } fmt.Printf("%v\n",res) fmt.Printf("\tThreat Type: %s\n",res.Matches[0].ThreatType) fmt.Printf("\tPlatform Type: %s\n",res.Matches[0].PlatformType) fmt.Printf("\tThreat Entry Type: %s\n",res.Matches[0].ThreatEntryType) fmt.Printf("\tURL: %s\n",res.Matches[0].Threat.URL) } 

是。 用gjson现在你所要做的就是:

bar := gjson.Get(json, "foo.bar")

如果你喜欢, bar可以是一个struct属性。 另外,没有地图。

那么匿名字段呢? 我不知道这是否构成一个“嵌套的结构”,但它比嵌套的结构声明更干净。 如果你想在其他地方重复使用嵌套元素呢?

 type NestedElement struct{ someNumber int `json:"number"` someString string `json:"string"` } type BaseElement struct { NestedElement `json:"bar"` }