serialize.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. package rest
  2. import (
  3. "fmt"
  4. "log"
  5. "reflect"
  6. "strings"
  7. "git.ali33.ru/fcg-xvii/go-tools/json"
  8. )
  9. // IRestConverter реализует пользовательский пасер из значения, полученного из запроса (см. пример из time.go)
  10. type IRestConverter interface {
  11. // RestFrom реализeт конвертацию из данных запроса в объект
  12. RestFrom(any) IErrorArgs
  13. }
  14. func parseVal(from, to reflect.Value, fieldName string) IErrorArgs {
  15. if from.Kind() == reflect.Interface {
  16. from = from.Elem()
  17. }
  18. if !from.CanConvert(to.Type()) {
  19. return NewError(
  20. "FieldType",
  21. json.Map{
  22. "field": fieldName,
  23. "expected": to.Type().String(),
  24. "received": from.Type().String(),
  25. },
  26. )
  27. }
  28. to.Set(from.Convert(to.Type()))
  29. return nil
  30. }
  31. func parseType(from, to reflect.Value, fieldName string) IErrorArgs {
  32. from = realValue(from)
  33. to = realValue(to)
  34. log.Println("=== to", to.Kind(), to.Type().Name())
  35. switch to.Kind() {
  36. case reflect.Interface:
  37. if from.Kind() != reflect.Invalid {
  38. to.Set(from)
  39. }
  40. return nil
  41. case reflect.Struct:
  42. return parseStruct(from, to, fieldName)
  43. case reflect.Slice:
  44. return parseSlice(from, to, fieldName)
  45. case reflect.Map:
  46. return parseMap(from, to, fieldName)
  47. default:
  48. return parseVal(from, to, fieldName)
  49. }
  50. }
  51. func realValue(val reflect.Value) reflect.Value {
  52. if val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
  53. if val.IsNil() && val.Kind() == reflect.Ptr {
  54. val.Set(reflect.New(val.Type().Elem()))
  55. }
  56. // check
  57. cval := val.Elem()
  58. if cval.Kind() == reflect.Invalid {
  59. return val
  60. }
  61. val = cval
  62. if val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
  63. return realValue(cval)
  64. }
  65. }
  66. return val
  67. }
  68. func parseSlice(from, to reflect.Value, fieldName string) IErrorArgs {
  69. if to.IsNil() {
  70. to.Set(reflect.MakeSlice(to.Type(), 0, from.Cap()))
  71. }
  72. eType := to.Type().Elem()
  73. // Перебираем элементы среза, откуда копируем.
  74. for i := 0; i < from.Len(); i++ {
  75. iFieldName := fmt.Sprintf("%v[%v]", fieldName, i)
  76. fromVal := from.Index(i)
  77. toVal := reflect.New(eType).Elem()
  78. if err := parseType(fromVal, toVal.Addr(), iFieldName); err != nil {
  79. return err
  80. }
  81. to.Set(reflect.Append(to, toVal))
  82. }
  83. return nil
  84. }
  85. func parseStruct(from, to reflect.Value, fieldName string) IErrorArgs {
  86. if f, check := to.Interface().(IRestConverter); check {
  87. return f.RestFrom(from.Interface())
  88. }
  89. if to.CanAddr() {
  90. if f, check := to.Addr().Interface().(IRestConverter); check {
  91. return f.RestFrom(from.Interface())
  92. }
  93. }
  94. loop:
  95. for i := 0; i < to.NumField(); i++ {
  96. required := false
  97. // устанавливаем тип и указатель поля объекта, куда копируем
  98. fType := to.Type().Field(i)
  99. fVal := to.Field(i)
  100. // проверяем тег, если он есть
  101. tag := fType.Tag.Get("rest")
  102. log.Println("=================================", fType.Name)
  103. if fType.Anonymous && fType.Type.Kind() == reflect.Ptr {
  104. log.Println("PTR...")
  105. elem := fType.Type.Elem()
  106. if elem.Kind() == reflect.Struct {
  107. log.Print("ELEM struct...")
  108. if fVal.IsNil() {
  109. log.Println("IS_NIL")
  110. fVal.Set(reflect.New(elem))
  111. log.Println(fVal.IsNil())
  112. }
  113. if ierr := parseStruct(from, fVal.Elem(), prefixFieldName(fieldName, fType.Name)); ierr != nil {
  114. return ierr
  115. }
  116. continue loop
  117. }
  118. }
  119. if len(tag) > 0 {
  120. required = strings.Contains(tag, "required")
  121. }
  122. var rVal reflect.Value
  123. switch from.Kind() {
  124. case reflect.Struct:
  125. if rVal = from.FieldByName(fType.Name); !rVal.IsValid() {
  126. rVal = from.FieldByName(camelToSnake(fType.Name))
  127. }
  128. case reflect.Map:
  129. if rVal = from.MapIndex(reflect.ValueOf(fType.Name)); !rVal.IsValid() {
  130. rVal = from.MapIndex(reflect.ValueOf(camelToSnake(fType.Name)))
  131. }
  132. default:
  133. return NewError(
  134. "FieldType",
  135. json.Map{
  136. "field": fieldName,
  137. "expected": to.Type().String(),
  138. "received": from.Type().String(),
  139. },
  140. )
  141. }
  142. if !rVal.IsValid() {
  143. if required {
  144. return ErrorMessage("RequiredField", fType.Name)
  145. }
  146. continue
  147. }
  148. if rVal.Kind() == reflect.Interface {
  149. rVal = rVal.Elem()
  150. }
  151. iFieldName := fmt.Sprintf("%v.%v", fieldName, fType.Name)
  152. if err := parseType(rVal, fVal.Addr(), iFieldName); err != nil {
  153. return err
  154. }
  155. }
  156. return nil
  157. }
  158. func parseMap(from, to reflect.Value, fieldName string) IErrorArgs {
  159. if to.IsNil() {
  160. to.Set(reflect.MakeMap(to.Type()))
  161. }
  162. switch from.Kind() {
  163. case reflect.Map:
  164. for _, key := range from.MapKeys() {
  165. iFieldName := fmt.Sprintf("%v[%v]", fieldName, key)
  166. fromVal := from.MapIndex(key)
  167. toVal := reflect.New(to.Type().Elem()).Elem()
  168. if err := parseType(fromVal, toVal.Addr(), iFieldName); err != nil {
  169. return err
  170. }
  171. to.SetMapIndex(key, toVal)
  172. }
  173. case reflect.Struct:
  174. for i := 0; i < from.NumField(); i++ {
  175. iFieldName := fmt.Sprintf("%v.%v", fieldName, from.Type().Field(i).Name)
  176. fromVal := from.Field(i)
  177. toVal := reflect.New(to.Type().Elem()).Elem()
  178. if err := parseType(fromVal, toVal.Addr(), iFieldName); err != nil {
  179. return err
  180. }
  181. fName := camelToSnake(from.Type().Field(i).Name)
  182. to.SetMapIndex(reflect.ValueOf(fName), toVal)
  183. }
  184. default:
  185. return NewError(
  186. "FieldType",
  187. json.Map{
  188. "field": fieldName,
  189. "expected": to.Type().String(),
  190. "received": from.Type().String(),
  191. },
  192. )
  193. }
  194. return nil
  195. }
  196. // Serialize преобразует словарь from в объект произвольного типа
  197. func Serialize(from json.Map, to any) IErrorArgs {
  198. elemTo := reflect.ValueOf(to).Elem()
  199. return parseType(
  200. reflect.ValueOf(&from),
  201. elemTo,
  202. "",
  203. )
  204. }