在Go中,我們經常需要將JSON轉換成結構體。有時候,我們不知道傳入的JSON數據類型是什么。這就需要使用反射來解決。
首先,我們需要創建一個結構體。例如:
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
接下來,我們需要寫一個函數來解析傳入的JSON數據,并將其賦值給結構體。這里我們使用反射來實現:
func populateStruct(data map[string]interface{}, result interface{}) error {
structValue := reflect.ValueOf(result).Elem()
for k, v := range data {
structFieldValue := structValue.FieldByNameFunc(func(fieldName string) bool {
return strings.ToLower(fieldName) == strings.ToLower(k)
})
if !structFieldValue.IsValid() {
continue
}
if !structFieldValue.CanSet() {
return fmt.Errorf("Cannot set %s field value", k)
}
val := reflect.ValueOf(v)
if structFieldValue.Type() != val.Type() {
return fmt.Errorf("Provided value %v of type %v did not match struct field type %v", v, val.Type(), structFieldValue.Type())
}
structFieldValue.Set(val)
}
return nil
}
這個函數接受兩個參數:傳入的JSON數據和一個空結構體。首先,我們使用反射獲取傳入的結構體中的字段,然后將其與傳入的JSON數據進行匹配。如果匹配成功,我們就將JSON數據賦值給對應的結構體字段。
下面是示例代碼:
func main() {
jsonData := []byte(`{"name":"John","age":30}`)
person := Person{}
err := json.Unmarshal(jsonData, &person)
if err != nil {
panic(err)
}
fmt.Println(person)
data := map[string]interface{}{
"name": "Jane",
"age": 25,
}
err = populateStruct(data, &person)
if err != nil {
panic(err)
}
fmt.Println(person)
}
在這個示例中,我們首先將傳入的JSON數據解析為結構體,然后通過反射將其更新為新的值。
通過使用這些技術,我們可以避免在編寫代碼時手動處理不同類型的JSON數據。