[英]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.com
( b
& c
)
题:
以我的经验,使用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.