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_test.go 7.2 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. package serder
  2. import (
  3. "fmt"
  4. "reflect"
  5. "testing"
  6. . "github.com/smartystreets/goconvey/convey"
  7. myreflect "gitlink.org.cn/cloudream/common/utils/reflect"
  8. )
  9. type FromAnyString struct {
  10. Str string
  11. }
  12. func (a *FromAnyString) FromAny(val any) (bool, error) {
  13. if str, ok := val.(string); ok {
  14. a.Str = "@" + str
  15. return true, nil
  16. }
  17. return false, nil
  18. }
  19. type ToAnyString struct {
  20. Str string
  21. }
  22. func (a *ToAnyString) ToAny(typ reflect.Type) (val any, ok bool, err error) {
  23. if typ == myreflect.TypeOf[map[string]any]() {
  24. return map[string]any{
  25. "str": "@" + a.Str,
  26. }, true, nil
  27. }
  28. return nil, false, nil
  29. }
  30. type FromAnySt struct {
  31. Value string
  32. }
  33. func (a *FromAnySt) FromAny(val any) (bool, error) {
  34. if st, ok := val.(ToAnySt); ok {
  35. a.Value = "From:" + st.Value
  36. return true, nil
  37. }
  38. return false, nil
  39. }
  40. type ToAnySt struct {
  41. Value string
  42. }
  43. func (a *ToAnySt) ToAny(typ reflect.Type) (val any, ok bool, err error) {
  44. if typ == myreflect.TypeOf[FromAnySt]() {
  45. return FromAnySt{
  46. Value: "To:" + a.Value,
  47. }, true, nil
  48. }
  49. return nil, false, nil
  50. }
  51. type DirToAnySt struct {
  52. Value string
  53. }
  54. func (a DirToAnySt) ToAny(typ reflect.Type) (val any, ok bool, err error) {
  55. if typ == myreflect.TypeOf[FromAnySt]() {
  56. return FromAnySt{
  57. Value: "DirTo:" + a.Value,
  58. }, true, nil
  59. }
  60. return nil, false, nil
  61. }
  62. func Test_AnyToAny(t *testing.T) {
  63. Convey("包含用字符串保存的int数据", t, func() {
  64. type Struct struct {
  65. A string `json:"a"`
  66. B int `json:"b"`
  67. C int64 `json:"c,string"`
  68. }
  69. mp := map[string]any{
  70. "a": "a",
  71. "b": 1,
  72. "c": "1234",
  73. }
  74. var st Struct
  75. err := AnyToAny(mp, &st)
  76. So(err, ShouldBeNil)
  77. So(st.A, ShouldEqual, "a")
  78. So(st.B, ShouldEqual, 1)
  79. So(st.C, ShouldEqual, 1234)
  80. })
  81. Convey("只有FromAny", t, func() {
  82. type Struct struct {
  83. Special FromAnyString `json:"str"`
  84. }
  85. mp := map[string]any{
  86. "str": "test",
  87. }
  88. var ret Struct
  89. err := AnyToAny(mp, &ret)
  90. So(err, ShouldBeNil)
  91. So(ret.Special.Str, ShouldEqual, "@test")
  92. })
  93. Convey("字段类型直接实现了FromAny", t, func() {
  94. type Struct struct {
  95. Special *FromAnyString `json:"str"`
  96. }
  97. mp := map[string]any{
  98. "str": "test",
  99. }
  100. var ret Struct
  101. err := AnyToAny(mp, &ret)
  102. So(err, ShouldBeNil)
  103. So(ret.Special.Str, ShouldEqual, "@test")
  104. })
  105. Convey("只有ToAny", t, func() {
  106. st := struct {
  107. Special ToAnyString `json:"str"`
  108. }{
  109. Special: ToAnyString{
  110. Str: "test",
  111. },
  112. }
  113. ret := map[string]any{}
  114. err := AnyToAny(st, &ret)
  115. So(err, ShouldBeNil)
  116. So(ret["str"].(map[string]any)["str"], ShouldEqual, "@test")
  117. })
  118. Convey("优先使用ToAny", t, func() {
  119. st1 := ToAnySt{
  120. Value: "test",
  121. }
  122. st2 := FromAnySt{}
  123. err := AnyToAny(st1, &st2)
  124. So(err, ShouldBeNil)
  125. So(st2.Value, ShouldEqual, "To:test")
  126. })
  127. Convey("使用Convertor", t, func() {
  128. type Struct1 struct {
  129. Value string
  130. }
  131. type Struct2 struct {
  132. Value string
  133. }
  134. st1 := Struct1{
  135. Value: "test",
  136. }
  137. st2 := Struct2{}
  138. err := AnyToAny(st1, &st2, AnyToAnyOption{
  139. Converters: []Converter{func(from reflect.Value, to reflect.Value) (interface{}, error) {
  140. if from.Type() == myreflect.TypeOf[Struct1]() && to.Type() == myreflect.TypeOf[Struct2]() {
  141. s1 := from.Interface().(Struct1)
  142. return Struct2{
  143. Value: "@" + s1.Value,
  144. }, nil
  145. }
  146. return nil, fmt.Errorf("should not arrive here!")
  147. }},
  148. })
  149. So(err, ShouldBeNil)
  150. So(st2.Value, ShouldEqual, "@test")
  151. })
  152. }
  153. func Test_MapToObject(t *testing.T) {
  154. type Base struct {
  155. Int int
  156. Bool bool
  157. String string
  158. Float float32
  159. }
  160. type ArraryStruct struct {
  161. IntArr []int
  162. StArr []Base
  163. ArrArr [][]int
  164. Nil []Base
  165. }
  166. type MapStruct struct {
  167. StrMap map[string]string
  168. StMap map[string]Base
  169. MapMap map[string]map[string]string
  170. Nil map[string]Base
  171. }
  172. type Top struct {
  173. ArrSt ArraryStruct
  174. MapSt *MapStruct
  175. BaseIf any
  176. NilPtr *Base
  177. }
  178. Convey("结构体递归转换成map[string]any", t, func() {
  179. val := Top{
  180. ArrSt: ArraryStruct{
  181. IntArr: []int{1, 2, 3},
  182. StArr: []Base{
  183. {
  184. Int: 1,
  185. Bool: true,
  186. String: "test",
  187. Float: 1,
  188. },
  189. {
  190. Int: 2,
  191. Bool: false,
  192. String: "test2",
  193. Float: 2,
  194. },
  195. },
  196. ArrArr: [][]int{
  197. {1, 2, 3},
  198. {},
  199. nil,
  200. },
  201. Nil: nil,
  202. },
  203. MapSt: &MapStruct{
  204. StrMap: map[string]string{
  205. "a": "1",
  206. "b": "2",
  207. },
  208. StMap: map[string]Base{
  209. "a": {
  210. Int: 1,
  211. Bool: true,
  212. String: "test",
  213. Float: 1,
  214. },
  215. "b": {
  216. Int: 2,
  217. Bool: false,
  218. String: "test2",
  219. Float: 2,
  220. },
  221. },
  222. MapMap: map[string]map[string]string{
  223. "a": {
  224. "a": "1",
  225. "b": "2",
  226. },
  227. "b": nil,
  228. },
  229. Nil: nil,
  230. },
  231. BaseIf: Base{
  232. Int: 1,
  233. Bool: true,
  234. String: "test",
  235. Float: 1,
  236. },
  237. NilPtr: nil,
  238. }
  239. retMp, err := ObjectToMap(val)
  240. So(err, ShouldBeNil)
  241. exceptMap := map[string]any{
  242. "ArrSt": map[string]any{
  243. "IntArr": []any{1, 2, 3},
  244. "StArr": []any{
  245. map[string]any{
  246. "Int": 1,
  247. "Bool": true,
  248. "String": "test",
  249. "Float": 1,
  250. },
  251. map[string]any{
  252. "Int": 2,
  253. "Bool": false,
  254. "String": "test2",
  255. "Float": 2,
  256. },
  257. },
  258. "ArrArr": []any{
  259. []any{1, 2, 3},
  260. []any{},
  261. []int(nil),
  262. },
  263. "Nil": []Base(nil),
  264. },
  265. "MapSt": map[string]any{
  266. "StrMap": map[string]any{
  267. "a": "1",
  268. "b": "2",
  269. },
  270. "StMap": map[string]any{
  271. "a": map[string]any{
  272. "Int": 1,
  273. "Bool": true,
  274. "String": "test",
  275. "Float": 1,
  276. },
  277. "b": map[string]any{
  278. "Int": 2,
  279. "Bool": false,
  280. "String": "test2",
  281. "Float": 2,
  282. },
  283. },
  284. "MapMap": map[string]any{
  285. "a": map[string]any{
  286. "a": "1",
  287. "b": "2",
  288. },
  289. "b": map[string]string(nil),
  290. },
  291. "Nil": map[string]Base(nil),
  292. },
  293. "BaseIf": map[string]any{
  294. "Int": 1,
  295. "Bool": true,
  296. "String": "test",
  297. "Float": 1,
  298. },
  299. "NilPtr": (*Base)(nil),
  300. }
  301. mpRetJson, err := ObjectToJSON(retMp)
  302. So(err, ShouldBeNil)
  303. exceptMapJson, err := ObjectToJSON(exceptMap)
  304. So(err, ShouldBeNil)
  305. So(string(mpRetJson), ShouldEqualJSON, string(exceptMapJson))
  306. })
  307. Convey("包含UnionType", t, func() {
  308. type UnionType interface{}
  309. type EleType1 struct {
  310. Value1 string `json:"value1"`
  311. }
  312. type EleType2 struct {
  313. Value2 int `json:"value2"`
  314. }
  315. type St struct {
  316. Us []UnionType `json:"us"`
  317. }
  318. mp := map[string]any{
  319. "us": []map[string]any{
  320. {
  321. "type": "1",
  322. "value1": "1",
  323. },
  324. {
  325. "type": "2",
  326. "value2": 2,
  327. },
  328. },
  329. }
  330. var ret St
  331. err := MapToObject(mp, &ret, MapToObjectOption{
  332. UnionTypes: []UnionTypeInfo{
  333. {
  334. UnionType: myreflect.TypeOf[UnionType](),
  335. TypeFieldName: "type",
  336. ElementTypes: NewStringTypeResolver().
  337. Add("1", myreflect.TypeOf[EleType1]()).
  338. Add("2", myreflect.TypeOf[EleType2]()),
  339. },
  340. },
  341. })
  342. So(err, ShouldBeNil)
  343. So(ret.Us, ShouldResemble, []UnionType{
  344. EleType1{Value1: "1"},
  345. EleType2{Value2: 2},
  346. })
  347. })
  348. }