原文地址声明:https://blog.csdn.net/qq_23179075/article/details/118394526
package common
import (
"fmt"
"reflect"
"strings"
)
// SetValueFromJsonTag 通过jsonTag设置 src 对象中的字段 , 支持类型: struct, slice
func SetValueFromJsonTag(src interface{}, jsonTag string, value interface{}) error {
valueOf := reflect.ValueOf(src)
kind := valueOf.Kind()
if kind == reflect.Ptr {
valueOf = valueOf.Elem()
kind = valueOf.Kind()
}
if kind == reflect.Struct {
return setStructValue(valueOf, jsonTag, value)
}
if kind == reflect.Slice || kind == reflect.Array {
return setSliceValue(valueOf, jsonTag, value)
}
return fmt.Errorf(`only struct|slice|array types are supported`)
}
func setStructValue(valueOf reflect.Value, jsonTag string, value interface{}) (err error) {
defer func() {
if rerr := recover(); rerr != nil {
err = fmt.Errorf("%v", rerr)
}
}()
vOf := reflect.ValueOf(value)
if vOf.Kind() == reflect.Ptr {
vOf = vOf.Elem()
}
for i := 0; i < valueOf.NumField(); i++ {
typeField := valueOf.Type().Field(i)
valueField := valueOf.Field(i)
//如果字段是匿名对象
if typeField.Anonymous {
if err = setStructValue(valueField, jsonTag, value); err == nil {
return nil
}
}
if getJsonTag(typeField) == jsonTag {
vu, err := getNewValue(valueField, vOf, jsonTag)
if err != nil {
return err
}
valueField.Set(vu)
return nil
}
}
return fmt.Errorf(`object does not have the json:"%v"`, jsonTag)
}
func setSliceValue(valueOf reflect.Value, jsonTag string, value interface{}) (err error) {
defer func() {
if rerr := recover(); rerr != nil {
err = fmt.Errorf("%v", rerr)
}
}()
vOf := reflect.ValueOf(value)
if vOf.Kind() == reflect.Ptr {
vOf = vOf.Elem()
}
for i := 0; i < valueOf.Len(); i++ {
item := valueOf.Index(i)
if item.Kind() == reflect.Ptr {
item = item.Elem()
}
if item.Kind() != reflect.Struct {
continue
}
if err = setStructValue(item, jsonTag, value); err != nil {
return err
}
}
return nil
}
func getNewValue(valueField reflect.Value, vOf reflect.Value, jsonTag string) (reflect.Value, error) {
if valueField.Kind() != vOf.Kind() {
if vOf.Kind() != reflect.Float64 {
return reflect.Value{}, fmt.Errorf(`value of type %v is not assignable to type json:"%v"->%v`, vOf.Kind(), jsonTag, valueField.Kind())
}
ivOf := vOf.Interface().(float64)
switch valueField.Kind() {
case reflect.Int:
return reflect.ValueOf(int(ivOf)), nil
case reflect.Int32:
return reflect.ValueOf(int32(ivOf)), nil
case reflect.Int64:
return reflect.ValueOf(int64(ivOf)), nil
case reflect.Float32:
return reflect.ValueOf(float32(ivOf)), nil
default:
return reflect.Value{}, fmt.Errorf(`value of type %v is not assignable to type json:"%v"->%v`, vOf.Kind(), jsonTag, valueField.Kind())
}
}
return vOf, nil
}
func getJsonTag(structField reflect.StructField) string {
fieldName := structField.Name
tag := structField.Tag.Get("json")
//fmt.Println("structField.Name:", fieldName, "; jsonTag:", tag,"; anonymous:",anonymous)
if tag == "" {
return fieldName
}
if strings.Contains(tag, ",") {
split := strings.Split(tag, ",")
if len(split) > 0 {
s := split[0]
if s == "" {
return fieldName
}
return s
}
}
return tag
}
测试用例
package common
import (
"fmt"
"testing"
)
type Form struct {
Name string `json:"name"`
Age int `json:"age"`
}
func TestFrom(t *testing.T) {
form := Form{Name: "张飞", Age: 24}
if err := SetValueFromJsonTag(&form, "name", "关羽"); err != nil {
fmt.Println(err)
}
fmt.Println(form)
if err := SetValueFromJsonTag(&form, "age", 32); err != nil {
fmt.Println(err)
}
fmt.Println(form)
if err := SetValueFromJsonTag(&form, "name", 32); err != nil {
fmt.Println(err)
}
fmt.Println(form)
if err := SetValueFromJsonTag(&form, "age", "关羽"); err != nil {
fmt.Println(err)
}
fmt.Println(form)
if err := SetValueFromJsonTag(&form, "sex", true); err != nil {
fmt.Println(err)
}
fmt.Println(form)
if err := SetValueFromJsonTag(form, "age", 48); err != nil {
fmt.Println(err)
}
fmt.Println(form)
}
func TestFroms(t *testing.T) {
forms := []Form{
{"刘备", 32},
{"张飞", 24},
{"关羽", 26},
}
if err := SetValueFromJsonTag(forms, "name", "赵云"); err != nil {
fmt.Println(err)
}
fmt.Println(forms)
if err := SetValueFromJsonTag(forms, "age", 32); err != nil {
fmt.Println(err)
}
fmt.Println(forms)
if err := SetValueFromJsonTag(forms, "name", 32); err != nil {
fmt.Println(err)
}
fmt.Println(forms)
if err := SetValueFromJsonTag(forms, "age", "关羽"); err != nil {
fmt.Println(err)
}
fmt.Println(forms)
if err := SetValueFromJsonTag(forms, "sex", true); err != nil {
fmt.Println(err)
}
fmt.Println(forms)
if err := SetValueFromJsonTag(&forms, "age", 48); err != nil {
fmt.Println(err)
}
fmt.Println(forms)
}