【发布时间】:2019-11-28 00:29:23
【问题描述】:
这里是新手 golang 程序员。我正在重写一个 Java 应用程序。 Java 应用程序使用一个对象模型,该模型利用 Jackson 的 Polymorphic Typing 功能来处理与 JSON 的编组/解组。假设我无法更改 JSON 对象的形状。
鉴于 Go 提供的多态性是 interface{},因此很难想出一个能够提供与多态性相同的使用模式的“对象模型”。
我第一次尝试解决的方法是这样的:
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 方法。
我试图通过创建“Union Structs”作为编组和解组的工具来解决这个问题:
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 而言,就能够编组和解组而言,这工作得很好。不利的一面是,模型的消费者需要对 Payload 进行类型断言,才能与子类型交互以完成任何实际工作。理想情况下,是否存在允许传递“事物”抽象级别的解决方案,该解决方案还允许在需要时与子类型进行交互?根据阅读,接口可以用于这种情况,但我很难看到这个模型将如何利用它们。想法?
【问题讨论】: