package rest import ( "errors" "fmt" "reflect" "git.ali33.ru/fcg-xvii/go-tools/json" ) type IFielder interface { Fields(...any) (json.Map, error) } type IFieldChecker interface { FieldCheck(string) bool } ///////////////////////////////////////////////// func NewFielder(source any) *Fielder { res := &Fielder{ source: source, fields: make(map[string]reflect.Value), } res._Prepare() return res } type Fielder struct { source any fields map[string]reflect.Value checker IFieldChecker } func (s *Fielder) _Prepare() { s.checker, _ = s.source.(IFieldChecker) val := reflect.ValueOf(s.source).Elem() for i := 0; i < val.NumField(); i++ { fName := val.Type().Field(i) field := val.Field(i) s.fields[CamelToSnake(fName.Name)] = field } } func (s *Fielder) Fields(names ...any) (json.Map, error) { res := make(json.Map) for _, rName := range names { var name string var fields []any if sName, check := rName.(string); check { name = sName } else if sMap, check := rName.(map[string]any); check { name = fmt.Sprint(sMap["name"]) if rFields, check := sMap["fields"]; check { if rxFields, check := rFields.([]any); check { fields = rxFields } } } permission := true if s.checker != nil { permission = s.checker.FieldCheck(name) } val, check := s.fields[name] if check && permission { iface := val.Interface() if val.Kind() == reflect.Ptr { if val.IsNil() { res[name] = nil } else { if fielder, check := iface.(IFielder); check { xVal, err := fielder.Fields(fields...) if err != nil { return nil, err } res[name] = xVal } } } else { res[name] = val.Interface() } } else { return nil, errors.New(name) } } return res, nil }