此处是新手golang程序员。我正在用go重写Java应用程序。 Java应用程序使用一个对象模型,该对象模型利用Jackson的Polymorphic Typing功能来处理与JSON的编组/解组。假设我无法更改JSON对象的形状。
鉴于go提供的多态性是接口{},因此提出一个“对象模型”以提供与多态性相同的使用模式一直是一项挑战。
我第一次尝试解决问题是这样的:
type Thing struct {
ID string `json:"id"`
Type string `json:"@type"`
}
type SpecificThing struct {
Thing
SpecificField string `json:"specificField"`
}
type AnotherSpecificThing struct {
Thing
AnotherSpecificField string `json:"anotherSpecificField"`
}
但这需要将具体的子类型实例传递给unmarshal方法。
我试图通过创建“联盟结构”作为元帅和元帅的工具来解决此问题:
type Thing struct {
ID string `json:"id"`
Type string `json:"@type"`
Payload interface{} `json:"-"`
}
type SpecificThing struct {
SpecificField string `json:"specificField"`
}
type AnotherSpecificThing struct {
AnotherSpecificField string `json:"anotherSpecificField"`
}
type superThing struct {
ID string `json:"id"`
Type string `json:"@type"`
*SpecificThing
*AnotherSpecificThing
}
func (t *Thing) UnmarshalJSON(b []byte) error {
//error checking omitted for brevity
var st superThing
_ = json.Unmarshal(b, &st)
t.ID = st.ID
t.Type = st.Type
switch t.Type {
case "specificThing":
t.Payload = st.SpecificThing
case "anotherSpecificThing":
t.Payload = st.AnotherSpecificThing
}
return nil
}
func TestUnmarshal(t *testing.T) {
data := []byte(`
{
"id":"some id",
"@type":"specificThing",
"specificField": "some specific field value"
}
`)
var th Thing
_ = json.Unmarshal(data, &th)
}
就此动态JSON而言,只要能够进行封送和解组,就可以很好地工作。不利的一面是,模型的使用者需要在有效载荷上进行类型声明,以与子类型进行交互以进行任何实际工作。理想情况下,是否存在一种解决方案可以绕过“事物”抽象层次,并且还可以在需要时与子类型进行交互?基于阅读,接口可以用于这种情况,但是我正在努力查看该模型如何利用它们。有想法吗?
答案 0 :(得分:0)
我认为使Thing成为接口并实现UnmarshalJSON可以为您提供所需的东西(如果用户需要接口不提供的功能,则用户仍然必须使用类型断言/切换,但这是不可避免的)。看起来类似于以下内容:
()=><p>hello world!</p>
Greg TrowBridge's blog中详细介绍了此方法。