1 回答
TA贡献1828条经验 获得超3个赞
我认为使 Thing 成为一个接口并实现 UnmarshalJSON 这几乎可以满足您的需求(如果用户需要接口未提供的功能,但这是不可避免的,他们仍然必须使用类型断言/开关)。这看起来像下面这样:
package main
import (
"encoding/json"
"fmt"
)
func main() {
data := []byte(`
{
"id":"some id",
"@type":"specificThing",
"specificField": "some specific field value"
}
`)
var th ThingHolder
err := json.Unmarshal(data, &th)
if err != nil {
panic(err)
}
mySpecThing := th.T.(*SpecificThing )
fmt.Printf("%v", mySpecThing)
}
type Thing interface {
ID() string
}
type ThingHolder struct {
T Thing
}
type SpecificThing struct {
Id string `json:"id"`
Type string `json:"@type"`
SpecificField string `json:"specificField"`
}
func (s *SpecificThing) ID() string {
return s.Id
}
func (t *ThingHolder) UnmarshalJSON(b []byte) error {
var objMap map[string]*json.RawMessage
err := json.Unmarshal(b, &objMap)
if err != nil {
return err
}
// Now lets see what 'things' the JSON contains
// by looking at JSON keys
jsonType, ok := objMap["@type"]
if !ok {
return fmt.Errorf("No Type")
}
var goType string
err = json.Unmarshal(*jsonType, &goType)
if err != nil {
return fmt.Errorf("error getting type: %s", err)
}
switch goType {
case "specificThing":
var st SpecificThing
err = json.Unmarshal(b, &st)
if err != nil {
return err
}
t.T = &st
default:
return fmt.Errorf("Unknown type %s", goType )
}
return nil
}
在OP指出我错过了一个测试用例后进行了更新。代码现已测试且工作正常。
- 1 回答
- 0 关注
- 117 浏览
添加回答
举报