在阅读了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
)
问题:
- 如果json是一个数组,我想遍历每个并打印电子邮件。
- 如果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)