You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

serder.go 5.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package serder
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "reflect"
  8. "strings"
  9. jsoniter "github.com/json-iterator/go"
  10. )
  11. var unionHandler = UnionHandler{
  12. internallyTagged: make(map[reflect.Type]*anyTypeUnionInternallyTagged),
  13. externallyTagged: make(map[reflect.Type]*anyTypeUnionExternallyTagged),
  14. }
  15. var defaultAPI = func() jsoniter.API {
  16. api := jsoniter.Config{
  17. EscapeHTML: true,
  18. }.Froze()
  19. api.RegisterExtension(&unionHandler)
  20. return api
  21. }()
  22. // 将对象转为JSON字符串。支持TypeUnion。
  23. func ObjectToJSONEx[T any](obj T) ([]byte, error) {
  24. buf := new(bytes.Buffer)
  25. enc := defaultAPI.NewEncoder(buf)
  26. // 这里使用&obj而直接不使用obj的原因是,Encode的形参类型为any,
  27. // 如果T是一个interface类型,将obj传递进去后,内部拿到的类型将会是obj的实际类型,
  28. // 使用&obj,那么内部拿到的将会是*T类型,通过一层一层解引用查找Encoder时,能找到T对应的TypeUnion
  29. err := enc.Encode(&obj)
  30. if err != nil {
  31. return nil, err
  32. }
  33. return buf.Bytes(), nil
  34. }
  35. // 将JSON字符串转为对象。支持TypeUnion。
  36. func JSONToObjectEx[T any](data []byte) (T, error) {
  37. var ret T
  38. dec := defaultAPI.NewDecoder(bytes.NewReader(data))
  39. err := dec.Decode(&ret)
  40. if err != nil {
  41. return ret, err
  42. }
  43. return ret, nil
  44. }
  45. // 将JSON字符串转为对象。支持TypeUnion。
  46. func JSONToObjectStreamEx[T any](stream io.Reader) (T, error) {
  47. var ret T
  48. dec := defaultAPI.NewDecoder(stream)
  49. err := dec.Decode(&ret)
  50. if err != nil {
  51. return ret, err
  52. }
  53. return ret, nil
  54. }
  55. // 将对象转为JSON字符串。如果需要支持解析TypeUnion类型,则使用"Ex"结尾的同名函数。
  56. func ObjectToJSON(obj any) ([]byte, error) {
  57. return json.Marshal(obj)
  58. }
  59. // 将对象转为JSON字符串。如果需要支持解析TypeUnion类型,则使用"Ex"结尾的同名函数。
  60. func ObjectToJSONStream(obj any) io.ReadCloser {
  61. pr, pw := io.Pipe()
  62. enc := json.NewEncoder(pw)
  63. go func() {
  64. err := enc.Encode(obj)
  65. if err != nil && err != io.EOF {
  66. pw.CloseWithError(err)
  67. } else {
  68. pw.Close()
  69. }
  70. }()
  71. return pr
  72. }
  73. // 将JSON字符串转为对象。如果需要支持解析TypeUnion类型,则使用"Ex"结尾的同名函数。
  74. func JSONToObject(data []byte, obj any) error {
  75. return json.Unmarshal(data, obj)
  76. }
  77. // 将JSON字符串转为对象。如果需要支持解析TypeUnion类型,则使用"Ex"结尾的同名函数。
  78. func JSONToObjectStream(str io.Reader, obj any) error {
  79. dec := json.NewDecoder(str)
  80. err := dec.Decode(obj)
  81. if err != io.EOF {
  82. return err
  83. }
  84. return nil
  85. }
  86. type TypeResolver interface {
  87. TypeToString(typ reflect.Type) (string, error)
  88. StringToType(typeStr string) (reflect.Type, error)
  89. }
  90. type MapToObjectOption struct {
  91. NoRegisteredUnionTypes bool // 是否不使用全局注册的UnionType
  92. }
  93. // TODO 使用这个函数来处理TypeUnion的地方都可以直接使用Ex系列的函数
  94. func MapToObject(m map[string]any, obj any, opt ...MapToObjectOption) error {
  95. var op MapToObjectOption
  96. if len(opt) > 0 {
  97. op = opt[0]
  98. }
  99. unionTypeMapping := make(map[reflect.Type]*anyTypeUnionInternallyTagged)
  100. if !op.NoRegisteredUnionTypes {
  101. for _, u := range unionHandler.internallyTagged {
  102. unionTypeMapping[u.Union.UnionType] = u
  103. }
  104. }
  105. convs := []Converter{
  106. func(from reflect.Value, to reflect.Value) (interface{}, error) {
  107. toType := to.Type()
  108. info, ok := unionTypeMapping[toType]
  109. if !ok {
  110. return from.Interface(), nil
  111. }
  112. mp := from.Interface().(map[string]any)
  113. tag, ok := mp[info.TagField]
  114. if !ok {
  115. return nil, fmt.Errorf("converting to %v: no tag field %s in map", toType, info.TagField)
  116. }
  117. tagStr, ok := tag.(string)
  118. if !ok {
  119. return nil, fmt.Errorf("converting to %v: tag field %s value is %v, which is not a string", toType, info.TagField, tag)
  120. }
  121. eleType, ok := info.TagToType[tagStr]
  122. if !ok {
  123. return nil, fmt.Errorf("converting to %v: unknow type tag %s", toType, tagStr)
  124. }
  125. to.Set(reflect.New(eleType).Elem())
  126. return from.Interface(), nil
  127. },
  128. }
  129. return AnyToAny(m, obj, AnyToAnyOption{
  130. Converters: convs,
  131. })
  132. }
  133. func ObjectToMap(obj any) (map[string]any, error) {
  134. ctx := WalkValue(obj, func(ctx *WalkContext, event WalkEvent) WalkingOp {
  135. switch e := event.(type) {
  136. case StructBeginEvent:
  137. mp := make(map[string]any)
  138. ctx.StackPush(mp)
  139. case StructArriveFieldEvent:
  140. if !WillWalkInto(e.Value) {
  141. ctx.StackPush(e.Value.Interface())
  142. }
  143. case StructLeaveFieldEvent:
  144. val := ctx.StackPop()
  145. mp := ctx.StackPeek().(map[string]any)
  146. jsonTag := e.Info.Tag.Get("json")
  147. if jsonTag == "-" {
  148. break
  149. }
  150. opts := strings.Split(jsonTag, ",")
  151. keyName := opts[0]
  152. if keyName == "" {
  153. keyName = e.Info.Name
  154. }
  155. if contains(opts, "string", 1) {
  156. val = fmt.Sprintf("%v", val)
  157. }
  158. mp[keyName] = val
  159. case StructEndEvent:
  160. case MapBeginEvent:
  161. ctx.StackPush(make(map[string]any))
  162. case MapArriveEntryEvent:
  163. if !WillWalkInto(e.Value) {
  164. ctx.StackPush(e.Value.Interface())
  165. }
  166. case MapLeaveEntryEvent:
  167. val := ctx.StackPop()
  168. mp := ctx.StackPeek().(map[string]any)
  169. mp[fmt.Sprintf("%v", e.Key)] = val
  170. case MapEndEvent:
  171. case ArrayBeginEvent:
  172. ctx.StackPush(make([]any, e.Value.Len()))
  173. case ArrayArriveElementEvent:
  174. if !WillWalkInto(e.Value) {
  175. ctx.StackPush(e.Value.Interface())
  176. }
  177. case ArrayLeaveElementEvent:
  178. val := ctx.StackPop()
  179. arr := ctx.StackPeek().([]any)
  180. arr[e.Index] = val
  181. case ArrayEndEvent:
  182. }
  183. return Next
  184. }, WalkOption{
  185. StackValues: []any{make(map[string]any)},
  186. })
  187. return ctx.StackPop().(map[string]any), nil
  188. }
  189. func contains(arr []string, ele string, startIndex int) bool {
  190. for i := startIndex; i < len(arr); i++ {
  191. if arr[i] == ele {
  192. return true
  193. }
  194. }
  195. return false
  196. }