简体   繁体   English

Go是否可以解组地图[string] [] interface {}?

[英]Is Go able to unmarshal to map[string][]interface{}?

Currently, I try to parse JSON to map[string][]interface{}, but unmarshalling returns an error. 目前,我尝试将JSON解析为map [string] [] interface {},但解组会返回错误。 According to ( https://golang.org/pkg/encoding/json/ ), to unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value: 根据( https://golang.org/pkg/encoding/json/ ),要将JSON解组为接口值,Unmarshal将其中之一存储在接口值中:

  • bool, for JSON booleans bool,用于JSON布尔值
  • float64, for JSON numbers float64,用于JSON数字
  • string, for JSON strings -[]interface{}, for JSON arrays 字符串,用于JSON字符串-[] interface {},用于JSON数组
  • map[string]interface{}, for JSON objects map [string] interface {},用于JSON对象
  • nil for JSON null 对于JSON为null

I wonder if golang is able to unmarshal map[string][]interface{}. 我不知道golang是否可以解组map [string] [] interface {}。 The following is code snippet. 以下是代码段。 I am new to Golang, thanks for help in advance. 我刚接触Golang,请先谢谢您的帮助。

// emailsStr looks like "{"isSchemaConforming":true,"schemaVersion":0,"unknown.0":[{"email_address":"test1@uber.com"},{"email_address":"test2@uber.com"}]}"

emailsRaw := make(map[string][]*entities.Email)
err := json.Unmarshal([]byte(emailsStr), &emailsRaw)

Error message: 错误信息:

&json.UnmarshalTypeError{Value:"number", Type:(*reflect.rtype)(0x151c7a0), Offset:44, Struct:"", Field:""} &json.UnmarshalTypeError {值:“数字”,类型:(* reflect.rtype)(0x151c7a0),偏移量:44,结构:“”,字段:“”}

The Go encoding/json package will only unmarshal dynamically to a map[string]interface{} . Go encoding/json程序包将仅动态解组到map[string]interface{} From there, you will need to use type assertions and casting to pull out the values you want, like so: 从那里,您将需要使用类型断言和强制转换来提取所需的值,如下所示:

func main() {
    jsonStr := `{"isSchemaConforming":true,"schemaVersion":0,"unknown.0":[{"email_address":"test1@uber.com"},{"email_address":"test2@uber.com"}]}`

    dynamic := make(map[string]interface{})
    json.Unmarshal([]byte(jsonStr), &dynamic)

    firstEmail := dynamic["unknown.0"].([]interface{})[0].(map[string]interface{})["email_address"]

    fmt.Println(firstEmail)
}

( https://play.golang.org/p/VEUEIwj3CIC ) https://play.golang.org/p/VEUEIwj3CIC

Each time, Go's .(<type>) operator is used to assert and cast the dynamic value to a specific type. 每次使用Go的.(<type>)运算符来断言并将动态值转换为特定类型。 This particular code will panic if anything happens to be the wrong type at runtime, like if the contents of unknown.0 aren't an array of JSON objects. 如果任何东西在运行时碰巧是错误的类型,则此特定代码将感到恐慌,例如unknown.0的内容不是JSON对象数组。

The more idiomatic (and robust) way to do this in Go is to annotate a couple structs with json:"" tags and have encoding/json unmarshal into them. 在Go中执行此操作的更惯用(更可靠)的方法是使用json:""标签注释几个结构,并对其进行encoding/json解组。 This avoids all the nasty brittle .([]interface{}) type casting: 这样可以避免所有讨厌的.([]interface{})类型转换:

type Email struct {
    Email string `json:"email_address"`
}

type EmailsList struct {
    IsSchemaConforming bool `json:"isSchemaConforming"`
    SchemaVersion      int  `json:"schemaVersion"`
    Emails []Email `json:"unknown.0"`
}

func main() {
    jsonStr := `{"isSchemaConforming":true,"schemaVersion":0,"unknown.0":[{"email_address":"test1@uber.com"},{"email_address":"test2@uber.com"}]}`

    emails := EmailsList{}
    json.Unmarshal([]byte(jsonStr), &emails)

    fmt.Printf("%+v\n", emails)
}

( https://play.golang.org/p/iS6e0_87P2J ) https://play.golang.org/p/iS6e0_87P2J

A better approach will be to use struct for main schema and then use an slice of email struct for fetching the data for email entities get the values from the same according to requirements. 更好的方法是将struct用于主架构,然后使用电子邮件结构的一部分来获取电子邮件实体的数据,以便根据需要从同一实体获取值。 Please find the solution below :- 请在下面找到解决方案:

package main

import (
    "fmt"
    "encoding/json"
)

type Data struct{
    IsSchemaConforming bool `json:"isSchemaConforming"`
    SchemaVersion float64 `json:"schemaVersion"`
    EmailEntity []Email `json:"unknown.0"`
}

// Email struct
type Email struct{
    EmailAddress string `json:"email_address"`
} 

func main() {
    jsonStr := `{"isSchemaConforming":true,"schemaVersion":0,"unknown.0":[{"email_address":"test1@uber.com"},{"email_address":"test2@uber.com"}]}`

    var dynamic Data
    json.Unmarshal([]byte(jsonStr), &dynamic)
    fmt.Printf("%#v", dynamic)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM