これを行うにはいくつかの方法がありますが、ペイロードの「AnimalType」属性に基づいて条件分岐を2回デシリアライズすることが最も簡単です。ここでは、中間デシリアライズモデルを使用した簡単な例です:
package main
import (
"fmt"
"encoding/json"
)
type Dog struct {
AnimalType string //will always be "dog"
BarkLoudnessLevel int
}
type Cat struct {
AnimalType string //will always be "cat"
SleepsAtNight bool
}
var (
payloadOne = `{"AnimalType":"dog","BarkLoudnessLevel":1}`
payloadTwo = `{"AnimalType":"cat","SleepsAtNight":false}`
)
func main() {
parseAnimal(payloadOne)
parseAnimal(payloadTwo)
}
func parseAnimal(payload string) {
animal := struct{
AnimalType string
}{}
if err := json.Unmarshal([]byte(payload), &animal); err != nil {
panic(err)
}
switch animal.AnimalType {
case "dog":
dog := Dog{}
if err := json.Unmarshal([]byte(payload), &dog); err != nil {
panic(err)
}
fmt.Printf("Got a dog: %v\n", dog)
case "cat":
cat := Cat{}
if err := json.Unmarshal([]byte(payload), &cat); err != nil {
panic(err)
}
fmt.Printf("Got a cat: %v\n", cat)
default:
fmt.Println("Unknown animal")
}
}
は、アクションhereでそれを参照してください。
IMO、これが予想されるJSONペイロードを変更する必要がありけれども、これは、親構造へのペイロードの「メタデータ」を移動している近づいてのより良い方法。あなたはのように見えたペイロードを使用していたのであれば、例えば、:
{"AnimalType":"dog", "Animal":{"BarkLoudnessLevel": 1}}
その後は、部分的な構造を解析し、必要に応じて、その後、条件付きで(むしろ二回すべてを解析するよりも)残りを解析するjson.RawMessage
のようなものを使用することができます - また、構造属性のより良い分離をもたらす。あなたがそれを行う方法の例を次に示します:
package main
import (
"encoding/json"
"fmt"
)
type Animal struct {
AnimalType string
Animal json.RawMessage
}
type Dog struct {
BarkLoudnessLevel int
}
type Cat struct {
SleepsAtNight bool
}
var (
payloadOne = `{"AnimalType":"dog", "Animal":{"BarkLoudnessLevel": 1}}`
payloadTwo = `{"AnimalType":"cat", "Animal":{"SleepsAtNight": false}}`
)
func main() {
parseAnimal(payloadOne)
parseAnimal(payloadTwo)
}
func parseAnimal(payload string) {
animal := &Animal{}
if err := json.Unmarshal([]byte(payload), &animal); err != nil {
panic(err)
}
switch animal.AnimalType {
case "dog":
dog := Dog{}
if err := json.Unmarshal(animal.Animal, &dog); err != nil {
panic(err)
}
fmt.Printf("Got a dog: %v\n", dog)
case "cat":
cat := Cat{}
if err := json.Unmarshal(animal.Animal, &cat); err != nil {
panic(err)
}
fmt.Printf("Got a cat: %v\n", cat)
default:
fmt.Println("Unknown animal")
}
}
そして、アクションhereです。
GoのWebサイト(https://golang.org/pkg/encoding/json/)で提供されている例を見てみましょう(「Example(CustomMarshalJSON)」を参照) –
「例(非マーシャル) "[' json.RawMessage'タイプ](https://golang.org/pkg/encoding/json/#RawMessage)のためのものです。 – maerics