Saya memiliki struct seperti ini:
type Result struct {
Data MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
Tetapi bahkan jika instance MyStruct benar-benar kosong (artinya, semua nilai adalah default), itu akan diserialkan sebagai:
"data":{}
Saya tahu bahwa dokumen encoding / json menentukan bahwa kolom "kosong" adalah:
false, 0, pointer nol atau nilai antarmuka, dan array, slice, peta, atau string apa pun dengan panjang nol
tetapi tanpa pertimbangan untuk struct dengan semua nilai kosong / default. Semua bidangnya juga diberi tag omitempty
, tetapi ini tidak berpengaruh.
Bagaimana saya bisa mendapatkan paket JSON untuk tidak mengatur bidang saya yang merupakan struct kosong?
&MyStruct{ /* values */ }
dihitung sebagai penunjuk nol? Nilainya tidak nihil.Seperti @chakrit disebutkan dalam komentar, Anda tidak bisa mendapatkan ini untuk bekerja dengan menerapkan
json.Marshaler
padaMyStruct
, dan menerapkan JSON kustom fungsi marshalling pada setiap struct yang menggunakan hal itu dapat lebih banyak bekerja. Itu benar-benar tergantung pada kasus penggunaan Anda, apakah itu sepadan dengan kerja ekstra atau apakah Anda siap untuk hidup dengan struct kosong di JSON Anda, tetapi inilah pola yang saya gunakan yang diterapkanResult
: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 }
Jika Anda memiliki struct besar dengan banyak bidang, ini bisa menjadi membosankan, terutama mengubah implementasi struct nanti, tetapi singkatnya menulis ulang seluruh
json
paket agar sesuai dengan kebutuhan Anda (bukan ide yang baik), ini adalah satu-satunya cara yang bisa saya pikirkan untuk mendapatkannya ini dilakukan sambil tetap menyimpan non-pointerMyStruct
di sana.Selain itu, Anda tidak harus menggunakan struct inline, Anda dapat membuat yang bernama. Saya menggunakan LiteIDE dengan penyelesaian kode, jadi saya lebih suka sebaris untuk menghindari kekacauan.
sumber
Data
adalah struct yang diinisialisasi, jadi tidak dianggap kosong karenaencoding/json
hanya melihat nilai langsung, bukan bidang di dalam struct.Sayangnya kembali
nil
darijson.Marhsler
saat ini tidak berfungsi:func (_ MyStruct) MarshalJSON() ([]byte, error) { if empty { return nil, nil // unexpected end of JSON input } // ... }
Anda bisa memberikan
Result
marshaler juga, tapi itu tidak sebanding dengan usahanya.Satu-satunya pilihan, seperti yang disarankan Matt, adalah membuat
Data
penunjuk dan menyetel nilainya kenil
.sumber
encoding/json
tidak dapat memeriksa bidang anak struct. Itu tidak akan sangat efisien, ya. Namun hal tersebut tentunya bukan tidak mungkin.json.Marshaler
kasus per kasus.MyStruct
kosong dengan menerapkanjson.Marshaler
padaMyStruct
dirinya sendiri. Bukti: play.golang.org/p/UEC8A3JGvxjson.Marshaler
padaResult
tipe yang memuat itu sendiri yang bisa sangat merepotkan.Ada proposal Golang yang luar biasa untuk fitur ini yang telah aktif selama lebih dari 4 tahun, jadi pada titik ini, dapat diasumsikan bahwa fitur ini tidak akan masuk ke perpustakaan standar dalam waktu dekat. Seperti yang ditunjukkan @Matt, pendekatan tradisionalnya adalah dengan mengubah struct menjadi pointers-to-struct . Jika pendekatan ini tidak layak (atau tidak praktis), maka alternatifnya adalah menggunakan encoder json alternatif yang tidak mendukung penghilangan struct nilai nol .
Saya membuat cermin dari pustaka Golang json ( clarketm / json ) dengan dukungan tambahan untuk menghilangkan struct nilai nol saat
omitempty
tag diterapkan. Library ini mendeteksi ke nol dengan cara yang mirip dengan encoder YAML go-yaml yang populer dengan memeriksa kolom struct publik secara rekursif .misalnya
$ go get -u "github.com/clarketm/json"
import ( "fmt" "github.com/clarketm/json" // drop-in replacement for `encoding/json` ) type Result struct { Data MyStruct `json:"data,omitempty"` Status string `json:"status,omitempty"` Reason string `json:"reason,omitempty"` } j, _ := json.Marshal(&Result{ Status: "204", Reason: "No Content", }) fmt.Println(string(j))
// Note: `data` is omitted from the resultant json. { "status": "204" "reason": "No Content" }
sumber