2016-08-03 3 views
4

awsでs3バケットのポリシーを変更しようとしています。ポリシーのために次のjson構造を作成しました。バケットポリシーを配置するためにはうまくいきます。現在のポリシーを取得して変更しようとすると、問題が発生します。値を配列にすることができるようにするjson用のGolang構造体

AWS、Action、またはResourceの値が1つのみのステートメントがある場合、Amazonは配列から単純な値に変換してアンマーシャリングを失敗させます。

AWS /アクション/リソースの値を文字列スライスまたは文字列に指定する方法はありますか?


は私が(例えば、github.com/Jeffail/gabs)ある程度この問題を回避するために使用することができることを利用可能なパッケージがあることを知っているが、それは非常に簡単ですので、それだけでJSON構造を作成するためにきれいになります。

+0

json文字列の両方の例を提供できますか? – huygn

+0

ところで、これらのjsonタグはすべてフィールド名と正確に一致するため、不要です。型にjsonタグがない場合は、代わりにフィールド名が使用されます – voutasaurus

+0

jsonタグが必要かどうかはわかりませんでしたが、実装にフィールドの名前を変更する必要がある場合にのみ必要です。 – arewm

答えて

2

interface{}の代わりに、MaybeSliceという型を作成し、カスタムMarshalJSONメソッドとUnmarshalJSONメソッドを実装できます。すべてのあなたのタイプ、この1つだけのためのカスタムマーシャラーを実装する必要はありませんので、MaybeSliceタイプはjson.Marshalとjson.Unmarshalが期待するインタフェースを満たすこれらのメソッドを実装することにより

type MaybeSlice []string 

func (ms *MaybeSlice) MarshalJSON() ([]byte, error) { 
    // Use normal json.Marshal for subtypes 
    if len(*ms) == 1 { 
     return json.Marshal(([]string)(*ms)[0]) 
    } 
    return json.Marshal(*ms) 
} 

func (ms *MaybeSlice) UnmarshalJSON(data []byte) error { 
    // Use normal json.Unmarshal for subtypes 
    var s string 
    if err := json.Unmarshal(data, &s); err != nil { 
     var v []string 
     if err := json.Unmarshal(data, &v); err != nil { 
      return err 
     } 
     *ms = v 
     return nil 
    } 
    *ms = []string{s} 
    return nil 
} 

おそらく、スライスはひどい名前ですが、うまくいけばアイデアを得ることができます。

これらのカスタムメソッドは、構造体型では簡単ですが、私は上記が正しいと思います。私が正しく覚えている場合は、Action*MaybeSliceとする必要があります。

+0

上記を使用した例:https://play.golang.org/p/X5Xauqwoz8 – voutasaurus

+0

私が欲しがったのと同じように働いた、ありがとう!私は自分でここに着き始めましたが、もうちょっと時間がかかりました。 :) – arewm

1

使用interface{}あなたが解析しようとしているフィールドの型が保証されない場合:

type Statement struct { 
    Sid  string `json:"Sid"` 
    Effect string `json:"Effect"` 
    Principal Principal `json:"Principal"` 

    Action interface{} `json:"Action"` 
    Resource interface{} `json:"Resource"` 
} 

と型スイッチを使用して、基礎となる元のデータ型にアクセス:

//Example: Trying to access Action member of a statement myStatement. 
switch a := myStatement.Action.(type) { 
    case []string: 
     //Action is a slice. Handle it accordingly. 
    case string: 
     //Action is a string. Handle it accordingly. 
    default: 
     //Some other datatype that can be returned by aws? 
} 

それとも、 Unmarshalingが失敗した場合、それを他の構造体に非整列化すると、次のようになります。

err := json.Unmarshal(jsonStr, &struct1) 
if err != nil { 
    fmt.Println(err) 
    err = json.Unmarshal(jsonStr, &struct2) 
} 
関連する問題