Why does this fail with the error :
json: cannot unmarshal object into Go struct field Person.spouse of type main.Spouse
type Spouse interface {
Name() // Adding this causes an error
}
type Address interface {
}
type Person struct {
Name string `json:"name"`
A *Address `json:"address"`
S *Spouse `json:"spouse"`
}
func main() {
b := []byte(`{
"name":"sarah",
"address":{
"street":"101 main"
},
"spouse":{
"name":"joe"
}
}
`)
p := &Person{}
if err := json.Unmarshal(b, p); err != nil {
fmt.Printf("%s", err)
}
}
Looking at the docs, I don't see why adding a function in an interface would cause an error. I was expecting json.Unmarshal to simply ignore the Name() function since it's not part of the list processed by json.Unmarshal.
Here is the code in go playground.
go version go1.10 darwin/amd64
答案 0 :(得分:4)
来自fine manual:
func Unmarshal
[...]
要将JSON解组为接口值,Unmarshal将其中一个存储在接口值中:bool, for JSON booleans float64, for JSON numbers string, for JSON strings []interface{}, for JSON arrays map[string]interface{}, for JSON objects nil for JSON null
您正在尝试将JSON对象解组为接口,因此该接口背后的值将是map[string]interface{}
来表示键/值对。但map[string]interface{}
没有Name()
方法,因此它不会实现您的Spouse
界面。
如果我们稍微简化您的示例并摆脱Name()
方法,我们可以看到正在发生的事情:
type Spouse interface {
}
type Person struct {
S *Spouse `json:"spouse"`
}
func main() {
b := []byte(`{"spouse":{ "name":"joe" } }`)
p := &Person{}
if err := json.Unmarshal(b, p); err != nil {
fmt.Printf("%s", err)
}
spouse := (*p.S).(map[string]interface{})
fmt.Printf("%+v\n", spouse)
}
spouse
是记录的map[string]interface{}
。
答案 1 :(得分:1)
问题在于您尝试使用不匹配的特定数据类型映射json中spouse
的值。正如this article中所报告的那样,json使用空接口将通用数据类型映射到文件中使用的正确数据类型。
json包使用
map[string]interface{}
和[]interface{}
值 存储任意JSON对象和数组;它会愉快地解散 任何有效的JSON blob到普通interface{}
值。默认 具体的Go类型是:
bool
用于JSON布尔值,float64
表示JSON号码,string
表示JSON字符串,nil
表示JSON为null。
如果您想从另一个角度看它,这意味着您不能使用除这些数据类型之外的任何内容来映射JSON中的数据。您的非空界面不是有效类型。