Saya telah membuat API in Go yang, saat dipanggil, melakukan kueri, membuat instance dari sebuah struct, dan kemudian menyandikan struct itu sebagai JSON sebelum mengirim kembali ke pemanggil. Sekarang saya ingin mengizinkan pemanggil untuk dapat memilih bidang spesifik yang ingin mereka kembalikan dengan mengirimkan parameter GET "bidang".
Ini berarti tergantung pada nilai bidang, struct saya akan berubah. Apakah ada cara untuk menghapus bidang dari struct? Atau setidaknya menyembunyikannya di respons JSON secara dinamis? (Catatan: Kadang-kadang saya memiliki nilai kosong sehingga tag omitEmpty JSON tidak akan berfungsi di sini) Jika tidak ada yang mungkin, apakah ada saran tentang cara yang lebih baik untuk menangani ini? Terima kasih sebelumnya.
Versi lebih kecil dari struct yang saya gunakan ada di bawah:
type SearchResult struct {
Date string `json:"date"`
IdCompany int `json:"idCompany"`
Company string `json:"company"`
IdIndustry interface{} `json:"idIndustry"`
Industry string `json:"industry"`
IdContinent interface{} `json:"idContinent"`
Continent string `json:"continent"`
IdCountry interface{} `json:"idCountry"`
Country string `json:"country"`
IdState interface{} `json:"idState"`
State string `json:"state"`
IdCity interface{} `json:"idCity"`
City string `json:"city"`
} //SearchResult
type SearchResults struct {
NumberResults int `json:"numberResults"`
Results []SearchResult `json:"results"`
} //type SearchResults
Saya kemudian menyandikan dan menampilkan respons seperti ini:
err := json.NewEncoder(c.ResponseWriter).Encode(&msg)
Jawaban:
EDIT: Saya perhatikan beberapa downvotes dan melihat lagi Q&A ini. Sebagian besar orang sepertinya ketinggalan bahwa OP meminta bidang menjadi dinamis dipilih berdasarkan daftar bidang yang disediakan pemanggil. Anda tidak dapat melakukan ini dengan tag json struct yang ditentukan secara statis.
Jika yang Anda inginkan adalah selalu melewatkan bidang ke json-encode, maka tentu saja gunakan
json:"-"
untuk mengabaikan bidang tersebut (juga perhatikan bahwa ini bukan diperlukan jika bidang Anda tidak diekspor - bidang tersebut selalu diabaikan oleh penyandi json). Tapi itu bukan pertanyaan OP.Mengutip komentar pada
json:"-"
jawabannya:Saya akan menggunakan antarmuka [string] peta {} alih-alih struct dalam hal ini. Anda dapat dengan mudah menghapus bidang dengan memanggil
delete
built-in pada peta untuk menghapus bidang.Yaitu, jika Anda tidak dapat meminta hanya untuk bidang yang diminta di tempat pertama.
sumber
map[string]interface{}
memang masuk akal, tetapi itu tidak mengharuskan Anda membuang definisi tipe Anda.Id
tetapi, tidak ingin mengembalikan seluruh json struct. Terima kasih untuk ini!gunakan `json:" - "`
doc: http://golang.org/pkg/encoding/json/#Marshal
sumber
Cara lain untuk melakukan ini adalah memiliki struct pointer dengan
,omitempty
tag. Jika petunjuknya nol , bidang tidak akan Marshall.Metode ini tidak memerlukan refleksi tambahan atau penggunaan peta yang tidak efisien.
Contoh yang sama seperti jorelli menggunakan metode ini: http://play.golang.org/p/JJNa0m2_nw
sumber
Anda dapat menggunakan
reflect
paket untuk memilih bidang yang Anda inginkan dengan merenungkan tag bidang dan memilih nilaijson
tag. Tentukan metode pada tipe SearchResults Anda yang memilih bidang yang Anda inginkan dan mengembalikannya sebagai amap[string]interface{}
, dan lalu buat itu sebagai ganti struct SearchResults itu sendiri. Berikut ini contoh bagaimana Anda dapat mendefinisikan metode itu:dan inilah solusi runnable yang menunjukkan bagaimana Anda akan memanggil metode ini dan menyusun pilihan Anda: http://play.golang.org/p/1K9xjQRnO8
sumber
Saya baru saja menerbitkan sheriff , yang mengubah struct ke peta berdasarkan tag yang dijelaskan pada bidang struct. Anda kemudian dapat menyusun (JSON atau yang lain) peta yang dihasilkan. Mungkin tidak memungkinkan Anda hanya membuat serial set bidang yang diminta oleh penelepon, tetapi saya membayangkan menggunakan serangkaian grup akan memungkinkan Anda untuk menutupi sebagian besar kasus. Menggunakan grup alih-alih bidang secara langsung kemungkinan besar juga akan meningkatkan kemampuan cache.
Contoh:
sumber
Ambil tiga bahan:
The
reflect
paket loop atas semua bidang struct.Sebuah
if
pernyataan untuk mengambil bidang yang ingin AndaMarshal
, danThe
encoding/json
paket untukMarshal
bidang sesuai dengan keinginan Anda.Persiapan:
Blender mereka dalam proporsi yang baik. Gunakan
reflect.TypeOf(your_struct).Field(i).Name()
untuk mendapatkan namai
bidang keyour_struct
.Gunakan
reflect.ValueOf(your_struct).Field(i)
untuk mendapatkanValue
representasi tipei
bidang ke-5your_struct
.Gunakan
fieldValue.Interface()
untuk mengambil nilai yang sebenarnya (upcasted untuk jenis antarmuka {}) darifieldValue
jenisValue
(perhatikan braket penggunaan - Interface () metode menghasilkaninterface{}
Jika Anda beruntung tidak membakar transistor atau pemutus sirkuit apa pun dalam proses, Anda harus mendapatkan sesuatu seperti ini:
Porsi:
melayani dengan struct sewenang-wenang dan
map[string]bool
bidang yang ingin Anda sertakan, misalnyaSelamat makan!
sumber
Anda dapat menggunakan atribut penandaan "omitifempty" atau membuat pointer bidang opsional dan membiarkan yang ingin Anda lewati diinisialisasi.
sumber
Saya juga menghadapi masalah ini, pada awalnya saya hanya ingin mengkhususkan respon di handler http saya. Pendekatan pertama saya adalah membuat paket yang menyalin informasi struct ke struct lain dan kemudian menyusun struct kedua itu. Saya melakukan paket itu menggunakan refleksi, jadi, tidak pernah menyukai pendekatan itu dan juga saya tidak dinamis.
Jadi saya memutuskan untuk memodifikasi paket encoding / json untuk melakukan ini. Fungsi
Marshal
,MarshalIndent
dan(Encoder) Encode
tambahan menerima atype F map[string]F
Saya ingin mensimulasikan JSON dari bidang yang diperlukan untuk marshal, sehingga hanya marsekal bidang yang ada di peta.
https://github.com/JuanTorr/jsont
sumber
Pertanyaannya sekarang sudah agak lama, tetapi saya menemukan masalah yang sama beberapa waktu yang lalu, dan karena saya tidak menemukan cara mudah untuk melakukan ini, saya membangun perpustakaan yang memenuhi tujuan ini. Hal ini memungkinkan untuk dengan mudah menghasilkan
map[string]interface{}
dari struct statis.https://github.com/tuvistavie/structomap
sumber
[]byte
adalah bahwa itu tidak terlalu dapat digunakan kembali: tidak ada cara mudah untuk menambahkan bidang sesudahnya, misalnya. Jadi saya akan menyarankan untuk membuatmap[string]interface{}
dan membiarkan bagian serialisasi JSON ke perpustakaan standar.Saya tidak memiliki masalah yang sama tetapi serupa. Kode di bawah ini memecahkan masalah Anda juga, tentu saja jika Anda tidak keberatan dengan masalah kinerja. Sebelum mengimplementasikan solusi semacam itu ke sistem Anda, saya sarankan Anda untuk mendesain ulang struktur Anda jika Anda bisa. Mengirim tanggapan struktur variabel adalah rekayasa berlebihan. Saya percaya struktur respons mewakili kontrak antara permintaan dan sumber daya dan tidak boleh tergantung pada permintaan. (Anda dapat membuat bidang yang tidak diinginkan menjadi nol, saya lakukan). Dalam beberapa kasus, kami harus menerapkan desain ini, jika Anda yakin Anda dalam hal ini, inilah tautan main dan kode yang saya gunakan.
sumber
Saya membuat fungsi ini untuk mengkonversi struct ke string JSON dengan mengabaikan beberapa bidang. Semoga ini bisa membantu.
Contoh: https://play.golang.org/p/nmq7MFF47Gp
sumber