解组到自定义接口

Ken*_*tov 4 json go

通常的解组方法是这样的:

atmosphereMap := make(map[string]interface{})
err := json.Unmarshal(bytes, &atmosphereMap)
Run Code Online (Sandbox Code Playgroud)

但是如何将json数据解组到自定义接口:

type CustomInterface interface {
    G() float64
} 

atmosphereMap := make(map[string]CustomInterface)
err := json.Unmarshal(bytes, &atmosphereMap)
Run Code Online (Sandbox Code Playgroud)

第二种方法给了我一个错误:

panic: json: cannot unmarshal object into Go value of type main.CustomInterface
Run Code Online (Sandbox Code Playgroud)

怎样做才正确呢?

Leo*_*eon 6

要解组为一组都实现公共接口的类型,您可以json.Unmarshaler在父类型上实现该接口,map[string]CustomInterface在您的情况下:

type CustomInterfaceMap map[string]CustomInterface

func (m CustomInterfaceMap) UnmarshalJSON(b []byte) error {
    data := make(map[string]json.RawMessage)
    if err := json.Unmarshal(b, &data); err != nil {
        return err
    }
    for k, v := range data {
        var dst CustomInterface
        // populate dst with an instance of the actual type you want to unmarshal into
        if _, err := strconv.Atoi(string(v)); err == nil {
            dst = &CustomImplementationInt{} // notice the dereference
        } else {
            dst = &CustomImplementationFloat{}
        }

        if err := json.Unmarshal(v, dst); err != nil {
            return err
        }
        m[k] = dst
    }
    return nil
}
Run Code Online (Sandbox Code Playgroud)

有关完整示例,请参阅此游乐场。确保您解组为CustomInterfaceMap, not ,否则将不会调用map[string]CustomInterface自定义方法。UnmarshalJSON

json.RawMessage是一个有用的类型,它只是一个原始编码的 JSON 值,这意味着它是一个简单的[]byte,JSON 以未解析的形式存储在其中。