是否可以解组来映射[string] [] interface {}?

时间:2018-02-11 03:21:16

标签: json go unmarshalling

目前,我尝试将JSON解析为map [string] [] interface {},但是解组会返回错误。根据(https://golang.org/pkg/encoding/json/),要将JSON解组为接口值,Unmarshal将其中一个存储在接口值中:

  • bool,适用于JSON布尔人
  • float64,用于JSON编号
  • 字符串,用于JSON字符串 - [] interface {},用于JSON数组
  • map [string] interface {},用于JSON对象
  • nil for JSON null

我想知道golang是否能够解组map [string] [] interface {}。以下是代码段。我是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)

错误讯息:

  

& json.UnmarshalTypeError {Value:" number",Type:(* reflect.rtype)(0x151c7a0),Offset:44,Struct:"",Field:& #34;"}

2 个答案:

答案 0 :(得分:0)

Go encoding/json包只会动态解组为map[string]interface{}。从那里,你需要使用类型断言和强制转换来提取你想要的值,如下所示:

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

每次使用Go的.(<type>)运算符来断言并将动态值转换为特定类型。如果在运行时发生任何错误的类型,这个特定代码将会出现混乱,例如unknown.0的内容不是JSON对象的数组。

在Go中执行此操作的更惯用(且更健壮)的方法是使用json:""标记注释几个结构并让encoding/json解组。这避免了所有讨厌的脆弱.([]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

答案 1 :(得分:0)

更好的方法是使用struct作为主模式,然后使用一段电子邮件结构来获取电子邮件实体的数据,根据需要从中获取相同的值。请找到以下解决方案: -

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)
}