serialize.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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. if !from.IsValid() {
  34. return nil
  35. }
  36. to = realValue(to)
  37. tn := StructTypeName(to)
  38. cv, check := fieldConverters[tn]
  39. if check {
  40. val, err := cv.Unpack(from.Interface())
  41. if err != nil {
  42. return NewError(
  43. "FieldValue",
  44. json.Map{
  45. "field": fieldName,
  46. "error": err.Error(),
  47. },
  48. )
  49. }
  50. to.Set(reflect.ValueOf(val))
  51. return nil
  52. }
  53. switch to.Kind() {
  54. case reflect.Interface:
  55. if from.Kind() != reflect.Invalid {
  56. to.Set(from)
  57. }
  58. return nil
  59. case reflect.Struct:
  60. return parseStruct(from, to, fieldName)
  61. case reflect.Slice:
  62. return parseSlice(from, to, fieldName)
  63. case reflect.Map:
  64. return parseMap(from, to, fieldName)
  65. default:
  66. return parseVal(from, to, fieldName)
  67. }
  68. }
  69. func realValue(val reflect.Value) reflect.Value {
  70. if val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
  71. //if val.Kind() == reflect.Interface {
  72. if val.IsNil() && val.Kind() == reflect.Ptr {
  73. log.Println(val.Type())
  74. val.Set(reflect.New(val.Type().Elem()))
  75. }
  76. // check
  77. cval := val.Elem()
  78. if cval.Kind() == reflect.Invalid {
  79. return val
  80. }
  81. val = cval
  82. if val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
  83. return realValue(cval)
  84. }
  85. }
  86. return val
  87. }
  88. func parseSlice(from, to reflect.Value, fieldName string) IErrorArgs {
  89. if to.IsNil() {
  90. to.Set(reflect.MakeSlice(to.Type(), 0, from.Cap()))
  91. }
  92. eType := to.Type().Elem()
  93. // Перебираем элементы среза, откуда копируем.
  94. for i := 0; i < from.Len(); i++ {
  95. iFieldName := fmt.Sprintf("%v[%v]", fieldName, i)
  96. fromVal := from.Index(i)
  97. toVal := reflect.New(eType).Elem()
  98. if err := parseType(fromVal, toVal.Addr(), iFieldName); err != nil {
  99. return err
  100. }
  101. to.Set(reflect.Append(to, toVal))
  102. }
  103. return nil
  104. }
  105. func parseStruct(from, to reflect.Value, fieldName string) IErrorArgs {
  106. if f, check := to.Interface().(IRestConverter); check {
  107. return f.RestFrom(from.Interface())
  108. }
  109. if to.CanAddr() {
  110. if f, check := to.Addr().Interface().(IRestConverter); check {
  111. return f.RestFrom(from.Interface())
  112. }
  113. }
  114. loop:
  115. for i := 0; i < to.NumField(); i++ {
  116. required := false
  117. // устанавливаем тип и указатель поля объекта, куда копируем
  118. fType := to.Type().Field(i)
  119. fVal := to.Field(i)
  120. if !fVal.CanSet() {
  121. continue
  122. }
  123. // проверяем тег, если он есть
  124. tag := fType.Tag.Get("rest")
  125. if fType.Anonymous && fType.Type.Kind() == reflect.Ptr {
  126. elem := fType.Type.Elem()
  127. if elem.Kind() == reflect.Struct {
  128. if fVal.IsNil() {
  129. fVal.Set(reflect.New(elem))
  130. }
  131. if ierr := parseStruct(from, fVal.Elem(), prefixFieldName(fieldName, fType.Name)); ierr != nil {
  132. return ierr
  133. }
  134. continue loop
  135. }
  136. }
  137. if len(tag) > 0 {
  138. required = strings.Contains(tag, "required")
  139. }
  140. var rVal reflect.Value
  141. switch from.Kind() {
  142. case reflect.Struct:
  143. if rVal = from.FieldByName(fType.Name); !rVal.IsValid() {
  144. rVal = from.FieldByName(fType.Name)
  145. }
  146. case reflect.Map:
  147. mapKeys := from.MapKeys()
  148. lowerFTypeName := strings.ToLower(fType.Name)
  149. for _, key := range mapKeys {
  150. lowerKey := strings.ToLower(key.String())
  151. if lowerKey == lowerFTypeName {
  152. rVal = from.MapIndex(key)
  153. break
  154. }
  155. }
  156. if !rVal.IsValid() {
  157. // Если ни один из ключей не совпал, попытаться найти по оригинальному ключу
  158. rVal = from.MapIndex(reflect.ValueOf(fType.Name))
  159. }
  160. default:
  161. return NewError(
  162. "FieldType",
  163. json.Map{
  164. "field": fieldName,
  165. "expected": to.Type().String(),
  166. "received": from.Type().String(),
  167. },
  168. )
  169. }
  170. if !rVal.IsValid() {
  171. if required {
  172. return ErrorMessage("RequiredField", fType.Name)
  173. }
  174. continue
  175. }
  176. if rVal.Kind() == reflect.Interface {
  177. rVal = rVal.Elem()
  178. }
  179. var iFieldName string
  180. if fieldName == "" {
  181. iFieldName = fType.Name
  182. } else {
  183. iFieldName = fmt.Sprintf("%v.%v", fieldName, fType.Name)
  184. }
  185. if err := parseType(rVal, fVal.Addr(), iFieldName); err != nil {
  186. return err
  187. }
  188. }
  189. return nil
  190. }
  191. func parseMap(from, to reflect.Value, fieldName string) IErrorArgs {
  192. if to.IsNil() {
  193. to.Set(reflect.MakeMap(to.Type()))
  194. }
  195. switch from.Kind() {
  196. case reflect.Map:
  197. for _, key := range from.MapKeys() {
  198. iFieldName := fmt.Sprintf("%v[%v]", fieldName, key)
  199. fromVal := from.MapIndex(key)
  200. toVal := reflect.New(to.Type().Elem()).Elem()
  201. if err := parseType(fromVal, toVal.Addr(), iFieldName); err != nil {
  202. return err
  203. }
  204. to.SetMapIndex(key, toVal)
  205. }
  206. case reflect.Struct:
  207. for i := 0; i < from.NumField(); i++ {
  208. iFieldName := fmt.Sprintf("%v.%v", fieldName, from.Type().Field(i).Name)
  209. fromVal := from.Field(i)
  210. toVal := reflect.New(to.Type().Elem()).Elem()
  211. if err := parseType(fromVal, toVal.Addr(), iFieldName); err != nil {
  212. return err
  213. }
  214. fName := from.Type().Field(i).Name
  215. to.SetMapIndex(reflect.ValueOf(fName), toVal)
  216. }
  217. default:
  218. return NewError(
  219. "FieldType",
  220. json.Map{
  221. "field": fieldName,
  222. "expected": to.Type().String(),
  223. "received": from.Type().String(),
  224. },
  225. )
  226. }
  227. return nil
  228. }
  229. // Serialize преобразует словарь from в объект произвольного типа
  230. func Serialize(from json.Map, to any) IErrorArgs {
  231. log.Println("serialize", from, to)
  232. log.Println(reflect.ValueOf(to).Type())
  233. elemTo := reflect.ValueOf(to).Elem()
  234. res := parseType(
  235. reflect.ValueOf(&from),
  236. elemTo,
  237. "",
  238. )
  239. log.Println("sres", res)
  240. return res
  241. }