doufu6504 2018-03-23 00:24
浏览 104
已采纳

为什么在接口中添加func会导致json.Unmarshal失败?

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

  • 写回答

2条回答 默认 最新

  • douyuan5600 2018-03-23 01:46
    关注

    From the fine manual:

    func Unmarshal
    [...]
    To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:

    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
    

    You're trying to unmarshal a JSON object into an interface so the value behind that interface is going to be a map[string]interface{} to represent the key/value pairs. But map[string]interface{} doesn't have a Name() method so it doesn't implement your Spouse interface.

    If we simplify your example a little and get rid of the Name() method we can see what's going on:

    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
    ", spouse)
    }
    

    spouse is a map[string]interface{} as documented.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥30 python代码,帮调试
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条