|
@@ -10,13 +10,81 @@ import (
|
|
|
)
|
|
|
|
|
|
type IRestFielder interface {
|
|
|
- RestFields(fieldName string, names ...any) (any, IErrorArgs)
|
|
|
+ RestFields(fieldName string, names FieldList) (any, IErrorArgs)
|
|
|
+}
|
|
|
+
|
|
|
+func FieldFromName(name string) *Field {
|
|
|
+ return &Field{
|
|
|
+ Name: name,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func FieldFromIface(val any) *Field {
|
|
|
+ res := &Field{}
|
|
|
+ if m, check := json.IsMap(val); check {
|
|
|
+ res.Name = strings.TrimSpace(m.String("name", ""))
|
|
|
+ if names := m.Slice("fields", nil); len(names) > 0 {
|
|
|
+ res.Names = FieldListFromSlice(names)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if str, check := val.(string); check {
|
|
|
+ res.Name = str
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return res
|
|
|
}
|
|
|
|
|
|
// Field реализует ...
|
|
|
type Field struct {
|
|
|
Name string
|
|
|
- Names []any
|
|
|
+ Names FieldList
|
|
|
+}
|
|
|
+
|
|
|
+func (s *Field) IsEmpty() bool {
|
|
|
+ return len(s.Name) == 0
|
|
|
+}
|
|
|
+
|
|
|
+func (s *Field) IsObject() bool {
|
|
|
+ return len(s.Names) == 0
|
|
|
+}
|
|
|
+
|
|
|
+func (s *Field) String() string {
|
|
|
+ res := "{ " + s.Name
|
|
|
+ if len(s.Names) > 0 {
|
|
|
+ res += " [ "
|
|
|
+ l := make([]string, len(s.Names))
|
|
|
+ for i, name := range s.Names {
|
|
|
+ l[i] = name.String()
|
|
|
+ }
|
|
|
+ res += strings.Join(l, ", ")
|
|
|
+ res += " ] "
|
|
|
+ }
|
|
|
+ res += " }"
|
|
|
+ return res
|
|
|
+}
|
|
|
+
|
|
|
+//////////////////////////////////////////////
|
|
|
+
|
|
|
+func FieldListFromNames(names ...string) FieldList {
|
|
|
+ res := make(FieldList, 0, len(names))
|
|
|
+ for _, name := range names {
|
|
|
+ res = append(res, FieldFromName(name))
|
|
|
+ }
|
|
|
+ return res
|
|
|
+}
|
|
|
+
|
|
|
+func FieldListFromSlice(f []any) FieldList {
|
|
|
+ res := make(FieldList, 0, len(f))
|
|
|
+ for _, v := range f {
|
|
|
+ if fd := FieldFromIface(v); !fd.IsEmpty() {
|
|
|
+ res = append(res, fd)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return res
|
|
|
+}
|
|
|
+
|
|
|
+func FieldListFromObjects(f ...any) FieldList {
|
|
|
+ return FieldListFromSlice(f)
|
|
|
}
|
|
|
|
|
|
type FieldList []*Field
|
|
@@ -42,19 +110,24 @@ type IFieldChecker interface {
|
|
|
RestFieldCheck(fieldName string) bool
|
|
|
}
|
|
|
|
|
|
-func fieldsDefault(t reflect.Type) (res []any) {
|
|
|
+func fieldsDefault(t reflect.Type) (res FieldList) {
|
|
|
for i := 0; i < t.NumField(); i++ {
|
|
|
fType := t.Field(i)
|
|
|
// проверяем тег, если он есть
|
|
|
tag := fType.Tag.Get("rest")
|
|
|
if len(tag) > 0 && (strings.Contains(tag, "default") || strings.Contains(tag, "fixed")) {
|
|
|
- res = append(res, fType.Name)
|
|
|
+ res = append(
|
|
|
+ res,
|
|
|
+ &Field{
|
|
|
+ Name: fType.Name,
|
|
|
+ },
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-func fieldsFixed(t reflect.Type) (res []any) {
|
|
|
+func fieldsFixed(t reflect.Type) (res FieldNamesList) {
|
|
|
for i := 0; i < t.NumField(); i++ {
|
|
|
fType := t.Field(i)
|
|
|
// проверяем тег, если он есть
|
|
@@ -84,10 +157,10 @@ func parseName(val reflect.Value) (res *Field, err error) {
|
|
|
err = fmt.Errorf("name is empty")
|
|
|
return
|
|
|
}
|
|
|
- fields := jm.Slice("fields", nil)
|
|
|
+ fields := jm.Slice("names", nil)
|
|
|
res = &Field{
|
|
|
Name: name,
|
|
|
- Names: fields,
|
|
|
+ Names: FieldListFromSlice(fields),
|
|
|
}
|
|
|
return
|
|
|
default:
|
|
@@ -96,14 +169,14 @@ func parseName(val reflect.Value) (res *Field, err error) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-func fieldVal(val reflect.Value, fieldName string, files RequestFiles, names ...any) (res reflect.Value, err IErrorArgs) {
|
|
|
+func fieldVal(val reflect.Value, fieldName string, files RequestFiles, names FieldList) (res reflect.Value, err IErrorArgs) {
|
|
|
switch val.Kind() {
|
|
|
case reflect.Ptr, reflect.Interface:
|
|
|
- return fieldVal(val.Elem(), fieldName, files, names...)
|
|
|
+ return fieldVal(val.Elem(), fieldName, files, names)
|
|
|
case reflect.Struct:
|
|
|
// check fielder interface
|
|
|
if f, check := val.Interface().(IRestFielder); check {
|
|
|
- rVal, err := f.RestFields(fieldName, names...)
|
|
|
+ rVal, err := f.RestFields(fieldName, names)
|
|
|
if err != nil {
|
|
|
return reflect.Value{}, err
|
|
|
}
|
|
@@ -113,7 +186,7 @@ func fieldVal(val reflect.Value, fieldName string, files RequestFiles, names ...
|
|
|
if val.CanAddr() {
|
|
|
// check fielder interface
|
|
|
if f, check := val.Addr().Interface().(IRestFielder); check {
|
|
|
- rVal, err := f.RestFields(fieldName, names...)
|
|
|
+ rVal, err := f.RestFields(fieldName, names)
|
|
|
if err != nil {
|
|
|
return reflect.Value{}, err
|
|
|
}
|
|
@@ -125,19 +198,11 @@ func fieldVal(val reflect.Value, fieldName string, files RequestFiles, names ...
|
|
|
names = fieldsDefault(val.Type())
|
|
|
}
|
|
|
jm := json.Map{}
|
|
|
- var fields FieldList
|
|
|
- addFieldVal := func(name any) bool {
|
|
|
- rField, rErr := parseName(reflect.ValueOf(name))
|
|
|
- if rErr != nil {
|
|
|
- message := fmt.Sprintf("%v: %v", name, err)
|
|
|
- err = ErrorFiled(fieldName, message)
|
|
|
- return false
|
|
|
- }
|
|
|
- fields = append(fields, rField)
|
|
|
+ addFieldVal := func(name *Field) bool {
|
|
|
var field reflect.Value
|
|
|
for i := 0; i < val.NumField(); i++ {
|
|
|
f := val.Type().Field(i)
|
|
|
- if f.Name == rField.Name {
|
|
|
+ if f.Name == name.Name {
|
|
|
tag := f.Tag.Get("rest")
|
|
|
if len(tag) > 0 && strings.Contains(tag, "ignore") {
|
|
|
return true
|
|
@@ -153,14 +218,16 @@ func fieldVal(val reflect.Value, fieldName string, files RequestFiles, names ...
|
|
|
var fVal reflect.Value
|
|
|
if fVal, err = fieldVal(
|
|
|
field,
|
|
|
- fmt.Sprintf("%v.%v", fieldName, rField.Name),
|
|
|
+ fmt.Sprintf("%v.%v", fieldName, name.Name),
|
|
|
files,
|
|
|
- rField.Names...,
|
|
|
+ name.Names,
|
|
|
); err != nil {
|
|
|
return false
|
|
|
}
|
|
|
- if fVal.IsValid() && !fVal.IsZero() {
|
|
|
- jm[rField.Name] = fVal.Interface()
|
|
|
+ if fVal.IsValid() {
|
|
|
+ jm[name.Name] = fVal.Interface()
|
|
|
+ } else {
|
|
|
+ jm[name.Name] = nil
|
|
|
}
|
|
|
return true
|
|
|
}
|
|
@@ -169,19 +236,20 @@ func fieldVal(val reflect.Value, fieldName string, files RequestFiles, names ...
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
// fields fixed
|
|
|
fFixed := fieldsFixed(val.Type())
|
|
|
for _, fixed := range fFixed {
|
|
|
- if !jm.KeyExists(fixed.(string)) {
|
|
|
- addFieldVal(fixed)
|
|
|
+ if !jm.KeyExists(fixed) {
|
|
|
+ addFieldVal(FieldFromName(fixed))
|
|
|
}
|
|
|
}
|
|
|
// post (когда результирующий объект уже сформирован)
|
|
|
if fielder, check := val.Interface().(IFielderPost); check {
|
|
|
- fielder.RestFieldsPost(jm, files, fields)
|
|
|
+ fielder.RestFieldsPost(jm, files, names)
|
|
|
} else if val.CanAddr() {
|
|
|
if fielder, check := val.Addr().Interface().(IFielderPost); check {
|
|
|
- fielder.RestFieldsPost(jm, files, fields)
|
|
|
+ fielder.RestFieldsPost(jm, files, names)
|
|
|
}
|
|
|
}
|
|
|
res = reflect.ValueOf(jm)
|
|
@@ -196,7 +264,7 @@ func fieldVal(val reflect.Value, fieldName string, files RequestFiles, names ...
|
|
|
val.Index(i),
|
|
|
fName,
|
|
|
files,
|
|
|
- names...,
|
|
|
+ names,
|
|
|
)
|
|
|
if err != nil {
|
|
|
return
|
|
@@ -211,7 +279,7 @@ func fieldVal(val reflect.Value, fieldName string, files RequestFiles, names ...
|
|
|
fName := fmt.Sprintf("%v[%v]", fieldName, key.String())
|
|
|
var rVal reflect.Value
|
|
|
iVal := val.MapIndex(key)
|
|
|
- rVal, err = fieldVal(iVal, fName, files)
|
|
|
+ rVal, err = fieldVal(iVal, fName, files, nil)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
@@ -224,9 +292,9 @@ func fieldVal(val reflect.Value, fieldName string, files RequestFiles, names ...
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func FieldsAny(obj any, files RequestFiles, names ...any) (any, IErrorArgs) {
|
|
|
+func FieldsAny(obj any, files RequestFiles, names FieldList) (any, IErrorArgs) {
|
|
|
sVal := reflect.ValueOf(obj)
|
|
|
- rVal, err := fieldVal(sVal.Elem(), "", files, names...)
|
|
|
+ rVal, err := fieldVal(sVal.Elem(), "", files, names)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
@@ -234,9 +302,9 @@ func FieldsAny(obj any, files RequestFiles, names ...any) (any, IErrorArgs) {
|
|
|
}
|
|
|
|
|
|
// Fields позволяет получить значения объекта в json
|
|
|
-func Fields(obj any, files RequestFiles, names ...any) (json.Map, IErrorArgs) {
|
|
|
+func Fields(obj any, files RequestFiles, names FieldList) (json.Map, IErrorArgs) {
|
|
|
sVal := reflect.ValueOf(obj)
|
|
|
- rVal, err := fieldVal(sVal.Elem(), "", files, names...)
|
|
|
+ rVal, err := fieldVal(sVal.Elem(), "", files, names)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
@@ -279,20 +347,25 @@ func FieldNames(s any) (FieldNamesList, error) {
|
|
|
|
|
|
/////////////////////////////////////////////
|
|
|
|
|
|
-func OutFields(req IRequestIn, obj any, files RequestFiles, names ...any) IRequestOut {
|
|
|
+func OutFields(req IRequestIn, obj any, files RequestFiles, names FieldList) IRequestOut {
|
|
|
if files == nil {
|
|
|
files = make(RequestFiles)
|
|
|
}
|
|
|
- m, err := Fields(obj, files, names...)
|
|
|
+ if len(names) == 0 {
|
|
|
+ names = req.Fields()
|
|
|
+ }
|
|
|
+ m, err := Fields(obj, files, names)
|
|
|
if err != nil {
|
|
|
return req.OutError(err)
|
|
|
}
|
|
|
return req.OutSuccess(m, files)
|
|
|
}
|
|
|
|
|
|
-func OutFieldsReq(req IRequestIn, obj any, files RequestFiles, names ...any) IRequestOut {
|
|
|
+/*
|
|
|
+func OutFieldsReq(req IRequestIn, obj any, files RequestFiles, names FieldList) IRequestOut {
|
|
|
if len(names) == 0 {
|
|
|
- names = req.RData().Slice("fields", nil)
|
|
|
+ names = req.Fields()
|
|
|
}
|
|
|
- return OutFields(req, obj, files, names...)
|
|
|
+ return OutFields(req, obj, files, names)
|
|
|
}
|
|
|
+*/
|