英文:
How to parse an inner field in a nested JSON object
问题
{
"name": "Cain",
"parents": {
"mother" : "Eve",
"father" : "Adam"
}
}
现在我想将"name"和"mother"解析到这个结构体中:
struct {
Name String
Mother String json:"???"
}
我想用json:...结构标签指定JSON字段名,但是我不知道该使用什么作为标签,因为我对顶层对象不感兴趣。我在encoding/json包的文档中找不到关于此的任何信息,也没有在流行的博客文章JSON and Go中找到。我还测试了mother,parents/mother和parents.mother。
英文:
I have a JSON object similar to this one:
{
  "name": "Cain",
  "parents": {
    "mother" : "Eve",
    "father" : "Adam"
  }
}
Now I want to parse "name" and "mother" into this struct:
struct {
  Name String
  Mother String `json:"???"`
}
I want to specify the JSON field name with the json:... struct tag, however I don't know what to use as tag, because it is not the top object I am interested in. I found nothing about this in the encoding/json package docs nor in the popular blog post JSON and Go. I also tested mother, parents/mother and parents.mother.
答案1
得分: 20
你可以使用结构体,只要你的输入数据不太动态。
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"
	    }
	}`
	// 解码json对象
	u := &User{}
	err := json.Unmarshal([]byte(encoded), &u)
	if err != nil {
		panic(err)
	}
	// 打印出母亲和父亲
	fmt.Printf("Mother: %s\n", u.Parents.Mother)
	fmt.Printf("Father: %s\n", u.Parents.Father)
}
英文:
You could use structs so long as your incoming data isn't too dynamic.
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)
}
答案2
得分: 19
不幸的是,与encoding/xml不同,json包没有提供访问嵌套值的方法。您可以创建一个单独的Parents结构体或将类型分配为map[string]string。例如:
type Person struct {
    Name string
    Parents map[string]string
}
然后,您可以提供一个获取母亲的方法:
func (p *Person) Mother() string {
    return p.Parents["mother"]
}
这可能与您当前的代码库有关,如果将Mother字段重构为方法调用不在计划中,那么您可能需要创建一个单独的方法来进行解码并符合您当前的结构体。
英文:
Unfortunately, unlike encoding/xml, the json package doesn't provide a way to access nested values. You'll want to either create a separate Parents struct or assign the type to be map[string]string. For example:
type Person struct {
    Name string
    Parents map[string]string
}
You could then provide a getter for mother as so:
func (p *Person) Mother() string {
    return p.Parents["mother"]
}
This may or may not play into your current codebase and if refactoring the Mother field to a method call is not on the menu, then you may want to create a separate method for decoding and conforming to your current struct.
答案3
得分: 6
这是我在Go Playground中快速编写的一些代码
http://play.golang.org/p/PiWwpUbBqt
package main
import (
	"fmt"
	"encoding/json"
	)
func main() {
	encoded := `{
	    "name": "Cain",
	    "parents": {
	        "mother": "Eve",
            "father": "Adam"
	    }
	}`
	// 解码json对象
	var j map[string]interface{}
	err := json.Unmarshal([]byte(encoded), &j)
	if err != nil {
		panic(err)
	}
	// 提取出parents对象
	parents := j["parents"].(map[string]interface{})
	// 打印出母亲和父亲
	fmt.Printf("Mother: %s\n", parents["mother"].(string))
	fmt.Printf("Father: %s\n", parents["father"].(string))
}
可能有更好的方法。我期待看到其他答案。 ![]()
英文:
Here's some code I baked up real quick in the 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))
}
There might be a better way.  I'm looking forward to seeing the other answers. ![]()
答案4
得分: 5
最近,gjson 支持选择嵌套的 JSON 属性。
name := gjson.Get(json, "name")
mother := gjson.Get(json, "parents.mother")
英文:
More recently, gjson supports selection of nested JSON properties.
name := gjson.Get(json, "name")
mother := gjson.Get(json, "parents.mother")
答案5
得分: 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)  
}
英文:
How about using an intermediary struct as the one suggested above for parsing, and then putting the relevant values in your "real" struct?
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)  
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论