使用反射自訂 JSON 解組
在 Go 中,將 JSON 解組為結構體是一個簡單的過程。然而,當處理具有自訂標籤的欄位時,例如 json:"some_field",標準的解組機制可能不夠。
處理這種情況的一種方法是使用反射。透過使用反射檢查結構體的字段,我們可以檢查字段是否具有特定標籤,如果有,則相應地處理其解組。
在這種特殊情況下,我們希望確保帶有 json 標籤的欄位是按原樣解組到字串欄位中。這使我們能夠在 Go 結構中處理 JSON 物件或陣列。
範例場景
考慮以下 JSON 資料與 Go 結構:
{
"I": 3,
"S": {
"phone": {
"sales": "2223334444"
}
}
}
type A struct {
I int64
S string `sql:"type:json"`
}
我們的目標是將「S」欄位解組為字串,保留其嵌套的 JSON 結構。
使用反射的解決方案
以下程式碼示範如何使用反射來實現這一點:
func main() {
a := A{}
// Unmarshal the JSON data into a byte slice
var data []byte
// Iterate over the fields of the struct
typ := reflect.TypeOf(a)
val := reflect.ValueOf(a)
for i := 0; i 在這種方法中,我們使用反射手動檢查結構體的每個字段,以確定它是否具有“json”標籤。如果是,我們將 JSON 資料作為字串解組到欄位中。
使用自訂編組器和解組器的替代解決方案
另一個選項是實作自訂類型,例如RawString,它實作了json.Marshaler和json .Unmarshaler介面。這允許對解組過程提供更大的靈活性和控制。
以下程式碼示範了這種方法:
// RawString is a raw encoded JSON object.
// It implements Marshaler and Unmarshaler and can
// be used to delay JSON decoding or precompute a JSON encoding.
type RawString string
// MarshalJSON returns *m as the JSON encoding of m.
func (m *RawString) MarshalJSON() ([]byte, error) {
return []byte(*m), nil
}
// UnmarshalJSON sets *m to a copy of data.
func (m *RawString) UnmarshalJSON(data []byte) error {
if m == nil {
return errors.New("RawString: UnmarshalJSON on nil pointer")
}
*m = RawString(data)
return nil
}
const data = `{"i":3, "S":{"phone": {"sales": "2223334444"}}}`
type A struct {
I int64
S RawString `sql:"type:json"`
}
func main() {
a := A{}
err := json.Unmarshal([]byte(data), &a)
if err != nil {
log.Fatal("Unmarshal failed", err)
}
fmt.Println("Done", a)
}
透過實作我們自己的類型,我們可以自訂解組過程並避免反射的需要,從而產生更乾淨、更有效率的解決方案。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3