Golang unmarshal json map & array



在阅读了JSON和Go之后,我确实了解了在Go中解码json的基础知识。但是,存在一个问题,输入json有时可以是映射,有时可以是映射数组。

请考虑以下问题:

package main
import (
    "encoding/json"
    "fmt"
)
func main() {
    b := []byte(`[{"email":"example@test.com"}]`)
    c := []byte(`{"email":"example@test.com"}`)
    var m interface{}
    json.Unmarshal(b, &m)
    switch v := m.(type) {
    case []interface{}:
        fmt.Println("this is b", v)
    default:
        fmt.Println("No type found")
    }
    json.Unmarshal(c, &m)
    switch v := m.(type) {
    case map[string]interface{}:
        fmt.Println("this is c", v)
    default:
        fmt.Println("No type found")
    }
}

现在,我如何获得值email:两种情况下example@test.combc

问题:

  1. 如果json是一个数组,我想遍历每个并打印电子邮件。
  2. 如果json是地图,我想直接打印电子邮件

玩: http://play.golang.org/p/UPoFxorqWl

根据我的经验,使用 interface{} 来处理 json 解码可能会导致一些奇怪的问题,我倾向于避免它。尽管有一些方法可以使用反射包来实现它。

这是基于您的原始解决方案的问题解决方案,希望对您有所帮助。

package main
import (
    "encoding/json"
    "fmt"
)
type Item struct {
    Email string `json:email`
}
func main() {
    b := []byte(`[{"email":"example_in_array@test.com"}]`)
    //b := []byte(`{"email":"example@test.com"}`)
    var m = &Item{}
    var ms = []*Item{}
    err := json.Unmarshal(b, &m)
    if err != nil {
        err = json.Unmarshal(b, &ms)
        if err != nil {
            panic(err)
        }
        for _, m := range ms {
            fmt.Println(m.Email)
        }
    } else {
        fmt.Println(m.Email)
    }
}

这是你想要的吗? http://play.golang.org/p/8yrirlUAnp

package main
import (
    "encoding/json"
    "fmt"
)
func main() {
    b := []byte(`[{"email":"example@test.com"}]`)
    c := []byte(`{"email":"example@test.com"}`)
    var m interface{}
    json.Unmarshal(b, &m)
    switch v := m.(type) {
    case []interface{}:
        for _, x := range v {
            fmt.Println("this is b", x.(map[string]interface{})["email"])
        }
    default:
        fmt.Println("No type found")
    }
    json.Unmarshal(c, &m)
    switch v := m.(type) {
    case map[string]interface{}:
        fmt.Println("this is c", v["email"])
    default:
        fmt.Println("No type found")
    }
}

编辑:错过了循环部分,添加了它。

这不是最惯用的,但另一种方法是尝试编组到您想要的类型。这样做的好处是,除了需要之外,没有额外的反射。

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

package main
import (
    "encoding/json"
    "fmt"
)
func main() {
    fmt.Println(extract([]byte(`[{"email":"example@test.com"}]`)))
    fmt.Println(extract([]byte(`{"email":"example@test.com"}`)))
}
func extract(b []byte) string {
    var m map[string]string
    err := json.Unmarshal(b, &m)
    if err == nil {
        return m["email"]
    }
    var nested []map[string]string
    err = json.Unmarshal(b, &nested)
    if err == nil {
        for _, m := range nested {
            return m["email"]
        }
    }
    return ""
}

你可以试试这个包

b := []byte(`[{"email":"example@test.com"}]`)
c := []byte(`{"email":"example@test.com"}`)
var m interface{}
var mm interface{}
json.Unmarshal(b, &m)
json.Unmarshal(c, &mm)
x := map[string]interface{}{
   "wrapped": m,
}
xx := map[string]interface{}{
   "wrapped": mm,
} 
var email string
if email_interface, err := GetProperty(x, "wrapped[0].email"); err == nil {
  email, _ = email_interface.(string)
}
if email_interface, err := GetProperty(xx, "wrapped.email"); err == nil {
  email, _ = email_interface.(string)
}

惯用方式:实现解编拆解器接口:

type Email struct {
    Val string `json:"email"`
}
func (this *Email) UnmarshalJSON(jsonBytes []byte) error {
    var err error
    type EmailStruct Email
    bytesBuffer := bytes.Buffer{}
    if jsonBytes[0] == '[' {
        emails := []EmailStruct{}
        err = json.Unmarshal(jsonBytes, &emails)
        if err != nil {
            return err
        }
        encoder := gob.NewEncoder(&bytesBuffer)
        err = encoder.Encode(&emails[0])
        if err != nil {
            return err
        }
        decoder := gob.NewDecoder(&bytesBuffer)
        err = decoder.Decode(this)
        if err != nil {
            return err
        }
        return err
    }
    email := EmailStruct{}
    err = json.Unmarshal(jsonBytes, &email)
    if err != nil {
        return err
    }
    encoder := gob.NewEncoder(&bytesBuffer)
    err = encoder.Encode(&email)
    if err != nil {
        return err
    }
    decoder := gob.NewDecoder(&bytesBuffer)
    err = decoder.Decode(this)
    if err != nil {
        return err
    }
    return err
}

使用"json。Unmarshal(jsonBytes, location)"来解码 json 字节。

email := Email{}
json.Unmarshal(jsonBytes, &email)

emails := []Email{}
json.Unmarshal(jsonBytes, &emails)

最新更新