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 關注
- 155 瀏覽
添加回答
舉報