json - 在匹配 Go 中的底层类型时将 JSON 解码为接口(interface)变量

标签 json generics go marshalling gob

我正在编写一个包装器来映射一些我需要的附加功能。一些最重要的事情是在保持通用性的同时编码和解码数据的能力。我设法使用 encoding/gob 编码器编写了一个编码器,但是如果编码的数据是人类可读的就更好了,我决定用 JSON 编写另一个实现。

通过使用 Register() 向通用接口(interface)变量传递一个实现对象实例,我得到了从通用接口(interface)变量编码和解码的 gob。 (此资源帮助我了解了详细信息!http://www.funcmain.com/gob_encoding_an_interface)

但是,JSON 没有 Register()。假设我们有一个类型的值

type ConcreteImplementation struct {
    FieldA string
    FieldB string
}

func (c ConcreteImplementation) Key() string {
    return c.FieldA   // ConcreteImplementation implements genericValue
}

在类型变量中

type genericValue interface {
    Key() string
}

当我整理它时,它会像这样输出 JSON:

{"FieldA":"foo","FieldB":"bar"}

当我尝试将其再次解码为 genericValue 类型的变量时,它说:

panic :接口(interface)转换:map[string]interface {} 不是 genericValue:缺少方法键 编辑:糟糕,实际上它是这样说的!

Error with decoding! json: cannot unmarshal object into Go value of genericValue

很明显,它会尝试像此处所说的那样编码数据:http://blog.golang.org/json-and-go (参见“带接口(interface)的通用 JSON{}”)

我怎样才能让它尝试使数据适合特定的实现,比如如果实现是 Register()ed,gob 解码器会尝试? Register() 是天赐之物,它允许一般地编码和解码,就像它什么都不是。如何让 JSON 执行相同的操作?

最佳答案

如果您的类型实现了 Unmarshaler 会怎么样? ?

Here is a small demo.

或此处相同的代码:

type ConcreteImplementation struct {
    FieldA string
    FieldB string
}

func (c ConcreteImplementation) Key() string {
    return c.FieldA // ConcreteImplementation implements genericValue
}

// implementing json.Unmarshaler
func (c *ConcreteImplementation) UnmarshalJSON(j []byte) error {
    m := make(map[string]string)
    err := json.Unmarshal(j, &m)
    if err != nil {
        return err
    }
    if v, ok := m["FieldA"]; ok {
        c.FieldA = v
    }
    if v, ok := m["FieldB"]; ok {
        c.FieldB = v
    }
    return nil
}

type genericValue interface {
    Key() string
    json.Unmarshaler
}

func decode(jsonStr []byte, v genericValue) error {
    return json.Unmarshal(jsonStr, v)
}

有了它,您可以将 genericValue 传递给 json.Unmarshal。

关于json - 在匹配 Go 中的底层类型时将 JSON 解码为接口(interface)变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22596260/

相关文章:

Java 泛型 - 编译错误

go - 如何将消息从一个 channel 分享到另一个 channel ?

javascript - jQuery .ajax() JSONP 响应的间歇性类型错误

iphone - iPhone 应用程序中的 JSON 解析

java - 在 Java 中提供 RESTful JSON API

c# - 在泛型方法中实例化泛型类型

java - Java 中任何对象的编译时类型与运行时类型之间有什么区别?

c# - 反序列化包含 csv 文件的 json 作为响应

go - 如何让 Go 覆盖浅色背景的 HTML?

multithreading - 从不同的线程读取值