| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 | package restimport (	"fmt"	"reflect"	"strings"	"git.ali33.ru/fcg-xvii/go-tools/json")func parseVal(from, to reflect.Value, fieldName string) IErrorArgs {	if from.Kind() == reflect.Interface {		from = from.Elem()	}	if !from.CanConvert(to.Type()) {		return NewError(			"FieldType",			json.Map{				"field":    fieldName,				"expected": to.Type().String(),				"received": from.Type().String(),			},		)	}	to.Set(from.Convert(to.Type()))	return nil}func parseType(from, to reflect.Value, fieldName string) IErrorArgs {	from = realValue(from)	to = realValue(to)	switch to.Kind() {	case reflect.Interface:		to.Set(from)		return nil	case reflect.Struct:		return parseStruct(from, to, fieldName)	case reflect.Slice:		return parseSlice(from, to, fieldName)	case reflect.Map:		return parseMap(from, to, fieldName)	default:		return parseVal(from, to, fieldName)	}}func realValue(val reflect.Value) reflect.Value {	//log.Println(val.IsNil())	if val.Kind() == reflect.Ptr {		if val.IsNil() {			val.Set(reflect.New(val.Type().Elem()))		}		val = val.Elem()		if val.Kind() == reflect.Ptr {			return realValue(val)		}	}	return val}func parseSlice(from, to reflect.Value, fieldName string) IErrorArgs {	if to.IsNil() {		to.Set(reflect.MakeSlice(to.Type(), 0, from.Cap()))	}	eType := to.Type().Elem()	// Перебираем элементы среза, откуда копируем.	for i := 0; i < from.Len(); i++ {		iFieldName := fmt.Sprintf("%v[%v]", fieldName, i)		fromVal := from.Index(i)		toVal := reflect.New(eType).Elem()		if err := parseType(fromVal, toVal.Addr(), iFieldName); err != nil {			return err		}		to.Set(reflect.Append(to, toVal))	}	return nil}func parseStruct(from, to reflect.Value, fieldName string) IErrorArgs {	for i := 0; i < to.NumField(); i++ {		required := false		// устанавливаем тип и указатель поля объекта, куда копируем		fType := to.Type().Field(i)		fVal := to.Field(i)		// проверяем тег, если он есть		tag := fType.Tag.Get("rest")		if len(tag) > 0 {			required = strings.Contains(tag, "required")		}		var rVal reflect.Value		switch from.Kind() {		case reflect.Struct:			if rVal = from.FieldByName(fType.Name); !rVal.IsValid() {				rVal = from.FieldByName(camelToSnake(fType.Name))			}		case reflect.Map:			if rVal = from.MapIndex(reflect.ValueOf(fType.Name)); !rVal.IsValid() {				rVal = from.MapIndex(reflect.ValueOf(camelToSnake(fType.Name)))			}		default:			return NewError(				"FieldType",				json.Map{					"field":    fieldName,					"expected": to.Type().String(),					"received": from.Type().String(),				},			)		}		if !rVal.IsValid() {			if required {				return ErrorMessage("RequiredField", fType.Name)			}			continue		}		if rVal.Kind() == reflect.Interface {			rVal = rVal.Elem()		}		iFieldName := fmt.Sprintf("%v.%v", fieldName, fType.Name)		if err := parseType(rVal, fVal.Addr(), iFieldName); err != nil {			return err		}	}	return nil}func parseMap(from, to reflect.Value, fieldName string) IErrorArgs {	if to.IsNil() {		to.Set(reflect.MakeMap(to.Type()))	}	switch from.Kind() {	case reflect.Map:		for _, key := range from.MapKeys() {			iFieldName := fmt.Sprintf("%v[%v]", fieldName, key)			fromVal := from.MapIndex(key)			toVal := reflect.New(to.Type().Elem()).Elem()			if err := parseType(fromVal, toVal.Addr(), iFieldName); err != nil {				return err			}			to.SetMapIndex(key, toVal)		}	case reflect.Struct:		for i := 0; i < from.NumField(); i++ {			iFieldName := fmt.Sprintf("%v.%v", fieldName, from.Type().Field(i).Name)			fromVal := from.Field(i)			toVal := reflect.New(to.Type().Elem()).Elem()			if err := parseType(fromVal, toVal.Addr(), iFieldName); err != nil {				return err			}			fName := camelToSnake(from.Type().Field(i).Name)			to.SetMapIndex(reflect.ValueOf(fName), toVal)		}	default:		return NewError(			"FieldType",			json.Map{				"field":    fieldName,				"expected": to.Type().String(),				"received": from.Type().String(),			},		)	}	return nil}func Serialize(from json.Map, to any) IErrorArgs {	elemTo := reflect.ValueOf(to).Elem()	return parseType(		reflect.ValueOf(&from),		elemTo,		"",	)}
 |