私はこのような構造を持っています:
type Result struct {
Data MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
ただし、MyStructのインスタンスが完全に空(つまり、すべての値がデフォルト)であっても、次のようにシリアル化されます。
"data":{}
encoding/json のドキュメントでは、「空の」フィールドが次のように指定されていることを知っています。
false、0、nilポインターまたはインターフェイス値、および長さゼロの配列、スライス、マップ、またはストリング
ただし、すべて空/デフォルト値を持つ構造体は考慮されません。すべてのフィールドにもomitempty
のタグが付いていますが、これは効果がありません。
JSONパッケージを取得して、空の構造体であるフィールドをnotマーシャリングするにはどうすればよいですか?
ああ!簡単な修正:「任意のnilポインター」。 -構造体をポインターにします。
修正:
type Result struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
*MyStruct
-MyStruct
を今作成するとき、私は単に参照によって作成します:
myStruct := &MyStruct{ /* values */ }
そして今、「空の」MyStruct
は、必要に応じてJSONにマーシャリングされなくなりました。
@chakritがコメントで言及したように、MyStruct
にjson.Marshaler
を実装し、それを使用するすべての構造体にカスタムJSONマーシャリング関数を実装しても、これを機能させることはできません。 。余分な作業に値するか、JSONで空の構造体を使用する準備ができているかどうかは、ユースケースに大きく依存しますが、Result
に適用するパターンは次のとおりです。
type Result struct {
Data MyStruct
Status string
Reason string
}
func (r Result) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}{
Data: &r.Data,
Status: r.Status,
Reason: r.Reason,
})
}
func (r *Result) UnmarshalJSON(b []byte) error {
decoded := new(struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
})
err := json.Unmarshal(b, decoded)
if err == nil {
r.Data = decoded.Data
r.Status = decoded.Status
r.Reason = decoded.Reason
}
return err
}
多くのフィールドを持つ巨大な構造体がある場合、特に構造体の実装を後で変更するのは面倒になりますが、必要に応じてjson
パッケージ全体を書き換える(良い考えではありません)ことは、これだけです私は、非ポインターMyStruct
を保持したまま、これを実行することを考えることができます。
また、インライン構造体を使用する必要はなく、名前付き構造体を作成できます。ただし、コード補完を使用してLiteIDEを使用しているため、混乱を避けるためにインラインを使用します。
Data
は初期化された構造体です。したがって、encoding/json
は構造体内のフィールドではなく即値のみを参照するため、空とは見なされません。
残念ながら、json.Marhsler
からnil
を返すことは現在機能していません。
func (_ MyStruct) MarshalJSON() ([]byte, error) {
if empty {
return nil, nil // unexpected end of JSON input
}
// ...
}
Result
にマーシャラーを与えることもできますが、努力する価値はありません。
Mattが示唆している唯一のオプションは、Data
をポインターにして、値をnil
に設定することです。