我正在尝试动态设置接口{}类型的字段。在下面的所有情况下,json 解组到正确的结构中,但在"问题"情况下,json 解组到 []interface{}。对于这种情况,我期待[]人。为什么我得到错误的"问题"类型?
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type Employees struct {
Indicator string `json:"indicator"`
Items interface{} `json:"items"`
}
type Person struct {
Name string `json:"name"`
}
func main() {
simple()
easy()
moreDifficult()
problem()
}
var j = []byte(`{"name": "bob"}`)
var jj = []byte(`[{"name": "bob"}, {"name": "jim"}, {"name": "fred"}]`)
func simple() {
p := Person{}
if err := json.Unmarshal(j, &p); err != nil {
fmt.Println(err)
}
fmt.Println("easy:", p, reflect.TypeOf(p))
}
func easy() {
p := []Person{}
if err := json.Unmarshal(jj, &p); err != nil {
fmt.Println(err)
}
fmt.Println("easy:", p, reflect.TypeOf(p))
}
func moreDifficult() {
var j = []byte(`{"indicator": "more difficult"}`)
e := Employees{}
if err := json.Unmarshal(j, &e); err != nil {
fmt.Println(err)
}
fmt.Println("moreDifficult", e.Items, reflect.TypeOf(e.Items))
}
func problem() {
var j = []byte(`{"indicator:": "problem"}`)
e := Employees{}
if err := json.Unmarshal(j, &e); err != nil {
fmt.Println(err)
}
fmt.Println("problem:", e.Items, reflect.TypeOf(e.Items)) // why not []Person???
}
func (e *Employees) UnmarshalJSON(b []byte) error {
type alias Employees
a := &alias{}
if err := json.Unmarshal(b, &a); err != nil {
return err
}
e.Indicator = a.Indicator
var k = jj
if e.Indicator == "more difficult" {
k = j
e.Items = &Person{}
} else {
e.Items = []Person{}
}
return json.Unmarshal(k, &e.Items)
}
https://play.golang.org/p/xQvjMyLTk5i
问题是接口的基础值不是指针:
e.Items = []Person{}
虽然您确实将指针传递给接口本身:
json.Unmarshal(k, &e.Items)
这并不能解决基础值为非指针的问题。
var a interface{} = &T{}
var b interface{} = T{}
b = &b
a
和b
的类型是不同的,解编拆收器将以不同的方式处理,在b
的情况下,解编拆收器将选择用map[string]interface{}
替换指向的值。
因此,要解决您的直接问题,您可以执行以下操作:
if e.Indicator == "more difficult" {
k = j
e.Items = &Person{}
} else {
e.Items = &[]Person{}
}
return json.Unmarshal(k, e.Items)
您当前的问题与 JSON 解组完全无关。
您将Items
定义为 类型 interface{}
,所以很明显,当您检查它时,它将是 interface{}
型 .如果您希望它是类型 []Person
,只需将其定义为:
type Employees struct {
Indicator string `json:"indicator"`
Items []Person `json:"items"`
}
完成此操作后,测试用例将产生预期的结果。但您的Items
仍将为空,因为您的输入 JSON 没有items
字段。