2017-06-06 7 views
1

は(もhttps://play.golang.org/p/or7z4Xc8tN参照)の例である:ここに埋め込まれた構造体の多JSONのアンマーシャル

package main 

import (
    "encoding/json" 
    "fmt" 
) 

type A struct { 
    X string 
    Y int 
} 

type B struct { 
    A 
    Y string 
} 

func main() { 
    data := []byte(`{"X": "me", "Y": "hi"}`) 
    b := &B{} 
    json.Unmarshal(data, b) 
    fmt.Println(b) 
    fmt.Println(b.A) 

    b = &B{} 
    data = []byte(`{"X": "me", "Y": 123}`) 
    json.Unmarshal(data, b) 
    fmt.Println(b) 
    fmt.Println(b.A) 
} 

出力:

&{{me 0} hi} 
{me 0} 
&{{me 0} } 
{me 0} 

をいずれかのint型にフィールドアンマーシャリングYをポリモーフィックする方法はありますまたは文字列ですか?また、B.Yが定義されているので、A.Yに非マーシャルさえできますか?

私は、json.Unmarshall(data, &b.A)のようなものでアンマーシャリングすることを提案するかもしれませんが、私はそれを現在のデザインに適合させることができるかどうかはわかりません。

+0

多分help https://stackoverflow.com/questions/32428797/unmarshal-to-a-interface-type –

答えて

1

Go's only polymorphismはインタフェースです。埋め込みは多態性を提供しません。

タイプ1のフィールドを想定できないJSONを非整列化しようとしている場合は、interface{}タイプのフィールドとタイプアサーション、fmt.Sprint、またはリフレクションを使用できます。使用する必要があるのは、特定のユースケースに依存します。いったん価値を得たら、それで何をするつもりですか?ある時点で、intstringかどうかを気にする必要があります。これにより、値の扱い方が決まります。

0

Adrianが指摘しているように、Goは構造体埋め込みによる多態性をサポートしていません。 interface{}は、あらゆるタイプのgolang変数を保持する唯一の方法です。しかし、あなたのケースでは、カスタムUnmarshalerを実装して、json.Numberまたはinterface{}を利用する構造体にJSONストリームをデコードすることができます。以下はjson.Numberを使用した実装です。より一般的なinterface{}バージョンについては、Adrianの提案に従って実装することができます。

func (b *B) UnmarshalJSON(js []byte) error { 
    //First: decode stream to anonymous struct 
    v := struct { 
     X string 
     Y json.Number 
    }{} 

    err := json.Unmarshal(js, &v) 
    if err != nil { 
     return err 
    } 

    //Depends on the v.Y value, choose the holder variable 
    //If it's convertible to number, assign to A.Y 
    //otherwise, assign it to b.Y 
    b.X = v.X 
    if fv, err := v.Y.Float64(); err == nil { 
     b.A.Y = int(fv) 
    } else { 
     b.Y = v.Y.String() 
    } 

    return nil 
} 

実例はThe Go Playgroundにあります。

関連する問題