Как разобрать внутреннее поле в вложенном объекте JSON в Голанге?
У меня есть объект JSON, похожий на этот:
{
"name": "Cain",
"parents": {
"mother" : "Eve",
"father" : "Adam"
}
}
Теперь я хочу проанализировать "имя" и "мать" в этой структуре:
struct {
Name String
Mother String `json:"???"`
}
Я хочу указать имя поля JSON с тегом json:...
struct, но я не знаю, что использовать в качестве тега, потому что это не главный объект, который меня интересует. Я ничего не нашел об этом в encoding/json
, а также в популярном сообщении в блоге JSON и Go. Я также тестировал mother
, parents/mother
и parents.mother
.
Ответы
Ответ 1
К сожалению, в отличие от encoding/xml
, пакет json
не предоставляет способ доступа к вложенным значениям. Вы захотите либо создать отдельную структуру Parents, либо назначить тип map[string]string
. Например:
type Person struct {
Name string
Parents map[string]string
}
Затем вы могли бы предоставить getter для матери:
func (p *Person) Mother() string {
return p.Parents["mother"]
}
Это может или не может воспроизводиться в вашей текущей кодовой базе, и если рефакторинг поля Mother
в вызове метода отсутствует в меню, тогда вам может понадобиться создать отдельный метод для декодирования и соответствия вашей текущей структуре.
Ответ 2
Вы можете использовать структуры, если ваши входящие данные не слишком динамичны.
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)
}
Ответ 3
Здесь некоторый код, который я быстро испек на игровой площадке Go
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))
}
Может быть, лучший способ. Я с нетерпением жду других ответов.: -)
Ответ 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)
}