Golang unmarshal json map&数组

时间:2016-02-29 04:05:46

标签: json go

阅读JSON and Go之后,我明白了在Go中解码json的基础知识。但是,有这个问题,输入json有时可能是map&有时是一系列地图。

考虑以下问题:

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.com

获得值bc

问题:

  1. 如果json是一个数组,我想循环遍历每个&打印电子邮件。
  2. 如果json是地图,我想直接打印电子邮件
  3. 播放:http://play.golang.org/p/UPoFxorqWl

5 个答案:

答案 0 :(得分:3)

根据我的经验,使用接口{}来处理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)
    }

}

答案 1 :(得分:2)

这是你想要的吗? 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")
    }

}

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

答案 2 :(得分:2)

这不是最惯用的,但另一种方法是尝试编组你想要的类型。这里的优点是没有超出需要的额外反射。

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

答案 3 :(得分:2)

您可以尝试this package

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

答案 4 :(得分:0)

惯用语方式:实现 Unmarshaler 界面:

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)

OR

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