繁体   English   中英

Golang解组JSON地图和数组

[英]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)
}

惯用的方式:实现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)

要么

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

暂无
暂无

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

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