package json import ( "fmt" "log" "reflect" ) // Заполняет поля структуры из map по тегам `jm` func FillStructFromMap(ptr any, data map[string]any) error { v := reflect.ValueOf(ptr) if v.Kind() != reflect.Ptr || v.IsNil() { return fmt.Errorf("expected pointer to struct") } v = v.Elem() if v.Kind() != reflect.Struct { return fmt.Errorf("expected pointer to struct") } t := v.Type() for i := 0; i < v.NumField(); i++ { field := t.Field(i) tag := field.Tag.Get("jm") if tag == "" || tag == "-" { continue } if val, ok := data[tag]; ok { fieldVal := v.Field(i) if fieldVal.CanSet() { valRef := reflect.ValueOf(val) if valRef.Type().ConvertibleTo(fieldVal.Type()) { fieldVal.Set(valRef.Convert(fieldVal.Type())) } } } } return nil } func FillFromJM(target any, data any) error { targetVal := reflect.ValueOf(target) if targetVal.Kind() != reflect.Ptr || targetVal.IsNil() { return fmt.Errorf("target must be a non-nil pointer") } elemVal := targetVal.Elem() log.Println() switch elemVal.Kind() { case reflect.Struct: // Single struct switch data := data.(type) { case Map: return FillStructFromMap(target, map[string]any(data)) case map[string]any: return FillStructFromMap(target, data) default: return fmt.Errorf("data must be map[string]any for struct input") } case reflect.Slice: // Slice of structs or pointers to structs maps, ok := data.([]map[string]any) if !ok { return fmt.Errorf("data must be []map[string]any for slice input") } sliceType := elemVal.Type() elemType := sliceType.Elem() for _, m := range maps { var newElem reflect.Value if elemType.Kind() == reflect.Ptr && elemType.Elem().Kind() == reflect.Struct { // []*Struct newPtr := reflect.New(elemType.Elem()) if err := FillStructFromMap(newPtr.Interface(), m); err != nil { return err } newElem = newPtr } else if elemType.Kind() == reflect.Struct { // []Struct newStruct := reflect.New(elemType) if err := FillStructFromMap(newStruct.Interface(), m); err != nil { return err } newElem = newStruct.Elem() } else { return fmt.Errorf("unsupported slice element type: %v", elemType.Kind()) } elemVal.Set(reflect.Append(elemVal, newElem)) } return nil default: return fmt.Errorf("target must be pointer to struct or slice") } }