阅读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
)
b
:c
问题:
答案 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)