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 12 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
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. package serder
  2. import (
  3. "fmt"
  4. "reflect"
  5. "testing"
  6. . "github.com/smartystreets/goconvey/convey"
  7. "gitlink.org.cn/cloudream/common/pkgs/types"
  8. "gitlink.org.cn/cloudream/common/utils/reflect2"
  9. )
  10. type FromAnyString struct {
  11. Str string
  12. }
  13. func (a *FromAnyString) FromAny(val any) (bool, error) {
  14. if str, ok := val.(string); ok {
  15. a.Str = "@" + str
  16. return true, nil
  17. }
  18. return false, nil
  19. }
  20. type ToAnyString struct {
  21. Str string
  22. }
  23. func (a *ToAnyString) ToAny(typ reflect.Type) (val any, ok bool, err error) {
  24. if typ == reflect2.TypeOf[map[string]any]() {
  25. return map[string]any{
  26. "str": "@" + a.Str,
  27. }, true, nil
  28. }
  29. return nil, false, nil
  30. }
  31. type FromAnySt struct {
  32. Value string
  33. }
  34. func (a *FromAnySt) FromAny(val any) (bool, error) {
  35. if st, ok := val.(ToAnySt); ok {
  36. a.Value = "From:" + st.Value
  37. return true, nil
  38. }
  39. return false, nil
  40. }
  41. type ToAnySt struct {
  42. Value string
  43. }
  44. func (a *ToAnySt) ToAny(typ reflect.Type) (val any, ok bool, err error) {
  45. if typ == reflect2.TypeOf[FromAnySt]() {
  46. return FromAnySt{
  47. Value: "To:" + a.Value,
  48. }, true, nil
  49. }
  50. return nil, false, nil
  51. }
  52. type DirToAnySt struct {
  53. Value string
  54. }
  55. func (a DirToAnySt) ToAny(typ reflect.Type) (val any, ok bool, err error) {
  56. if typ == reflect2.TypeOf[FromAnySt]() {
  57. return FromAnySt{
  58. Value: "DirTo:" + a.Value,
  59. }, true, nil
  60. }
  61. return nil, false, nil
  62. }
  63. func Test_AnyToAny(t *testing.T) {
  64. Convey("包含用字符串保存的int数据", t, func() {
  65. type Struct struct {
  66. A string `json:"a"`
  67. B int `json:"b"`
  68. C int64 `json:"c,string"`
  69. }
  70. mp := map[string]any{
  71. "a": "a",
  72. "b": 1,
  73. "c": "1234",
  74. }
  75. var st Struct
  76. err := AnyToAny(mp, &st)
  77. So(err, ShouldBeNil)
  78. So(st.A, ShouldEqual, "a")
  79. So(st.B, ShouldEqual, 1)
  80. So(st.C, ShouldEqual, 1234)
  81. })
  82. Convey("只有FromAny", t, func() {
  83. type Struct struct {
  84. Special FromAnyString `json:"str"`
  85. }
  86. mp := map[string]any{
  87. "str": "test",
  88. }
  89. var ret Struct
  90. err := AnyToAny(mp, &ret)
  91. So(err, ShouldBeNil)
  92. So(ret.Special.Str, ShouldEqual, "@test")
  93. })
  94. Convey("字段类型直接实现了FromAny", t, func() {
  95. type Struct struct {
  96. Special *FromAnyString `json:"str"`
  97. }
  98. mp := map[string]any{
  99. "str": "test",
  100. }
  101. var ret Struct
  102. err := AnyToAny(mp, &ret)
  103. So(err, ShouldBeNil)
  104. So(ret.Special.Str, ShouldEqual, "@test")
  105. })
  106. Convey("只有ToAny", t, func() {
  107. st := struct {
  108. Special ToAnyString `json:"str"`
  109. }{
  110. Special: ToAnyString{
  111. Str: "test",
  112. },
  113. }
  114. ret := map[string]any{}
  115. err := AnyToAny(st, &ret)
  116. So(err, ShouldBeNil)
  117. So(ret["str"].(map[string]any)["str"], ShouldEqual, "@test")
  118. })
  119. Convey("优先使用ToAny", t, func() {
  120. st1 := ToAnySt{
  121. Value: "test",
  122. }
  123. st2 := FromAnySt{}
  124. err := AnyToAny(st1, &st2)
  125. So(err, ShouldBeNil)
  126. So(st2.Value, ShouldEqual, "To:test")
  127. })
  128. Convey("使用Convertor", t, func() {
  129. type Struct1 struct {
  130. Value string
  131. }
  132. type Struct2 struct {
  133. Value string
  134. }
  135. st1 := Struct1{
  136. Value: "test",
  137. }
  138. st2 := Struct2{}
  139. err := AnyToAny(st1, &st2, AnyToAnyOption{
  140. Converters: []Converter{func(from reflect.Value, to reflect.Value) (interface{}, error) {
  141. if from.Type() == reflect2.TypeOf[Struct1]() && to.Type() == reflect2.TypeOf[Struct2]() {
  142. s1 := from.Interface().(Struct1)
  143. return Struct2{
  144. Value: "@" + s1.Value,
  145. }, nil
  146. }
  147. return nil, fmt.Errorf("should not arrive here!")
  148. }},
  149. })
  150. So(err, ShouldBeNil)
  151. So(st2.Value, ShouldEqual, "@test")
  152. })
  153. }
  154. func Test_MapToObject(t *testing.T) {
  155. type Base struct {
  156. Int int
  157. Bool bool
  158. String string
  159. Float float32
  160. }
  161. type ArraryStruct struct {
  162. IntArr []int
  163. StArr []Base
  164. ArrArr [][]int
  165. Nil []Base
  166. }
  167. type MapStruct struct {
  168. StrMap map[string]string
  169. StMap map[string]Base
  170. MapMap map[string]map[string]string
  171. Nil map[string]Base
  172. }
  173. type Top struct {
  174. ArrSt ArraryStruct
  175. MapSt *MapStruct
  176. BaseIf any
  177. NilPtr *Base
  178. }
  179. Convey("结构体递归转换成map[string]any", t, func() {
  180. val := Top{
  181. ArrSt: ArraryStruct{
  182. IntArr: []int{1, 2, 3},
  183. StArr: []Base{
  184. {
  185. Int: 1,
  186. Bool: true,
  187. String: "test",
  188. Float: 1,
  189. },
  190. {
  191. Int: 2,
  192. Bool: false,
  193. String: "test2",
  194. Float: 2,
  195. },
  196. },
  197. ArrArr: [][]int{
  198. {1, 2, 3},
  199. {},
  200. nil,
  201. },
  202. Nil: nil,
  203. },
  204. MapSt: &MapStruct{
  205. StrMap: map[string]string{
  206. "a": "1",
  207. "b": "2",
  208. },
  209. StMap: map[string]Base{
  210. "a": {
  211. Int: 1,
  212. Bool: true,
  213. String: "test",
  214. Float: 1,
  215. },
  216. "b": {
  217. Int: 2,
  218. Bool: false,
  219. String: "test2",
  220. Float: 2,
  221. },
  222. },
  223. MapMap: map[string]map[string]string{
  224. "a": {
  225. "a": "1",
  226. "b": "2",
  227. },
  228. "b": nil,
  229. },
  230. Nil: nil,
  231. },
  232. BaseIf: Base{
  233. Int: 1,
  234. Bool: true,
  235. String: "test",
  236. Float: 1,
  237. },
  238. NilPtr: nil,
  239. }
  240. retMp, err := ObjectToMap(val)
  241. So(err, ShouldBeNil)
  242. exceptMap := map[string]any{
  243. "ArrSt": map[string]any{
  244. "IntArr": []any{1, 2, 3},
  245. "StArr": []any{
  246. map[string]any{
  247. "Int": 1,
  248. "Bool": true,
  249. "String": "test",
  250. "Float": 1,
  251. },
  252. map[string]any{
  253. "Int": 2,
  254. "Bool": false,
  255. "String": "test2",
  256. "Float": 2,
  257. },
  258. },
  259. "ArrArr": []any{
  260. []any{1, 2, 3},
  261. []any{},
  262. []int(nil),
  263. },
  264. "Nil": []Base(nil),
  265. },
  266. "MapSt": map[string]any{
  267. "StrMap": map[string]any{
  268. "a": "1",
  269. "b": "2",
  270. },
  271. "StMap": map[string]any{
  272. "a": map[string]any{
  273. "Int": 1,
  274. "Bool": true,
  275. "String": "test",
  276. "Float": 1,
  277. },
  278. "b": map[string]any{
  279. "Int": 2,
  280. "Bool": false,
  281. "String": "test2",
  282. "Float": 2,
  283. },
  284. },
  285. "MapMap": map[string]any{
  286. "a": map[string]any{
  287. "a": "1",
  288. "b": "2",
  289. },
  290. "b": map[string]string(nil),
  291. },
  292. "Nil": map[string]Base(nil),
  293. },
  294. "BaseIf": map[string]any{
  295. "Int": 1,
  296. "Bool": true,
  297. "String": "test",
  298. "Float": 1,
  299. },
  300. "NilPtr": (*Base)(nil),
  301. }
  302. mpRetJson, err := ObjectToJSON(retMp)
  303. So(err, ShouldBeNil)
  304. exceptMapJson, err := ObjectToJSON(exceptMap)
  305. So(err, ShouldBeNil)
  306. So(string(mpRetJson), ShouldEqualJSON, string(exceptMapJson))
  307. })
  308. Convey("包含UnionType", t, func() {
  309. type EleType string
  310. type UnionType interface{}
  311. type EleType1 struct {
  312. Metadata `union:"1"`
  313. Type EleType `json:"type"`
  314. Value1 string `json:"value1"`
  315. }
  316. type EleType2 struct {
  317. Metadata `union:"2"`
  318. Type EleType `json:"type"`
  319. Value2 int `json:"value2"`
  320. }
  321. type St struct {
  322. Us []UnionType `json:"us"`
  323. }
  324. mp := map[string]any{
  325. "us": []map[string]any{
  326. {
  327. "type": "1",
  328. "value1": "1",
  329. },
  330. {
  331. "type": "2",
  332. "value2": 2,
  333. },
  334. },
  335. }
  336. var ret St
  337. union := types.NewTypeUnion[UnionType](
  338. (*EleType1)(nil),
  339. (*EleType2)(nil),
  340. )
  341. UseTypeUnionInternallyTagged(&union, "type")
  342. err := MapToObject(mp, &ret)
  343. So(err, ShouldBeNil)
  344. So(ret.Us, ShouldResemble, []UnionType{
  345. &EleType1{Type: "1", Value1: "1"},
  346. &EleType2{Type: "2", Value2: 2},
  347. })
  348. })
  349. Convey("要转换到的结构体就是一个UnionType", t, func() {
  350. type UnionType interface{}
  351. type EleType1 struct {
  352. Metadata `union:"1"`
  353. Type string `json:"type"`
  354. Value1 string `json:"value1"`
  355. }
  356. type EleType2 struct {
  357. Metadata `union:"2"`
  358. Type string `json:"type"`
  359. Value2 int `json:"value2"`
  360. }
  361. mp := map[string]any{
  362. "type": "1",
  363. "value1": "1",
  364. }
  365. var ret UnionType
  366. union := types.NewTypeUnion[UnionType](
  367. (*EleType1)(nil),
  368. (*EleType2)(nil),
  369. )
  370. UseTypeUnionInternallyTagged(&union, "type")
  371. err := MapToObject(mp, &ret)
  372. So(err, ShouldBeNil)
  373. So(ret, ShouldResemble, &EleType1{Type: "1", Value1: "1"})
  374. })
  375. Convey("NewType", t, func() {
  376. type Str string
  377. type St struct {
  378. Str Str
  379. }
  380. mp := map[string]any{
  381. "Str": "1",
  382. }
  383. var ret St
  384. err := MapToObject(mp, &ret)
  385. So(err, ShouldBeNil)
  386. So(string(ret.Str), ShouldEqual, "1")
  387. })
  388. }
  389. type Base interface {
  390. Noop()
  391. }
  392. type St1 struct {
  393. Metadata `union:"St1"`
  394. Type string
  395. Val string
  396. }
  397. func (*St1) Noop() {}
  398. type St2 struct {
  399. Metadata `union:"St2"`
  400. Type string
  401. Val int
  402. }
  403. func (St2) Noop() {}
  404. func Test_ObjectToJSON2(t *testing.T) {
  405. Convey("NewType", t, func() {
  406. type Str string
  407. type St struct {
  408. Str Str `json:"str"`
  409. }
  410. st := St{
  411. Str: Str("1"),
  412. }
  413. data, err := ObjectToJSON(st)
  414. So(err, ShouldBeNil)
  415. var ret St
  416. err = JSONToObject(data, &ret)
  417. So(err, ShouldBeNil)
  418. So(string(ret.Str), ShouldEqual, "1")
  419. })
  420. Convey("UnionType ExternallyTagged", t, func() {
  421. type Base interface{}
  422. type St1 struct {
  423. Val string
  424. }
  425. type St2 struct {
  426. Val int64
  427. }
  428. type Outter struct {
  429. B []Base
  430. }
  431. union := types.NewTypeUnion[Base](St1{}, &St2{})
  432. UseTypeUnionExternallyTagged(&union)
  433. val := Outter{B: []Base{St1{Val: "asd"}, &St2{Val: 123}}}
  434. data, err := ObjectToJSONEx(val)
  435. So(err, ShouldBeNil)
  436. ret, err := JSONToObjectEx[Outter](data)
  437. So(err, ShouldBeNil)
  438. So(ret, ShouldResemble, val)
  439. })
  440. Convey("UnionType InternallyTagged", t, func() {
  441. type Base interface{}
  442. type St1 struct {
  443. Metadata `union:"St1"`
  444. Type string
  445. Val string
  446. }
  447. type St2 struct {
  448. Metadata `union:"St2"`
  449. Type string
  450. Val int64
  451. }
  452. type Outter struct {
  453. B []Base
  454. }
  455. union := types.NewTypeUnion[Base](St1{}, &St2{})
  456. UseTypeUnionInternallyTagged(&union, "Type")
  457. val := Outter{B: []Base{St1{Val: "asd", Type: "St1"}, &St2{Val: 123, Type: "St2"}}}
  458. data, err := ObjectToJSONEx(val)
  459. So(err, ShouldBeNil)
  460. ret, err := JSONToObjectEx[Outter](data)
  461. So(err, ShouldBeNil)
  462. So(ret, ShouldResemble, val)
  463. })
  464. Convey("实参类型和目标类型本身就是UnionType ExternallyTagged", t, func() {
  465. type Base interface{}
  466. type St1 struct {
  467. Val string
  468. }
  469. union := types.NewTypeUnion[Base](St1{})
  470. UseTypeUnionExternallyTagged(&union)
  471. var val Base = St1{Val: "asd"}
  472. data, err := ObjectToJSONEx(val)
  473. So(err, ShouldBeNil)
  474. ret, err := JSONToObjectEx[Base](data)
  475. So(err, ShouldBeNil)
  476. So(ret, ShouldResemble, val)
  477. })
  478. Convey("实参类型和目标类型本身就是UnionType InternallyTagged", t, func() {
  479. type Base interface{}
  480. type St1 struct {
  481. Metadata `union:"St1"`
  482. Type string
  483. Val string
  484. }
  485. union := types.NewTypeUnion[Base](St1{})
  486. UseTypeUnionInternallyTagged(&union, "Type")
  487. var val Base = St1{Val: "asd", Type: "St1"}
  488. data, err := ObjectToJSONEx(val)
  489. So(err, ShouldBeNil)
  490. ret, err := JSONToObjectEx[Base](data)
  491. So(err, ShouldBeNil)
  492. So(ret, ShouldResemble, val)
  493. })
  494. Convey("UnionType带有函数 ExternallyTagged", t, func() {
  495. union := types.NewTypeUnion[Base](&St1{}, St2{})
  496. UseTypeUnionExternallyTagged(&union)
  497. var val []Base = []Base{
  498. &St1{Val: "asd", Type: "St1"},
  499. St2{Val: 123, Type: "St2"},
  500. }
  501. data, err := ObjectToJSONEx(val)
  502. So(err, ShouldBeNil)
  503. ret, err := JSONToObjectEx[[]Base](data)
  504. So(err, ShouldBeNil)
  505. So(ret, ShouldResemble, val)
  506. })
  507. Convey("UnionType带有函数 InternallyTagged", t, func() {
  508. union := types.NewTypeUnion[Base](&St1{}, St2{})
  509. UseTypeUnionInternallyTagged(&union, "Type")
  510. var val []Base = []Base{
  511. &St1{Val: "asd", Type: "St1"},
  512. St2{Val: 123, Type: "St2"},
  513. }
  514. data, err := ObjectToJSONEx(val)
  515. So(err, ShouldBeNil)
  516. ret, err := JSONToObjectEx[[]Base](data)
  517. So(err, ShouldBeNil)
  518. So(ret, ShouldResemble, val)
  519. })
  520. Convey("UnionType,但实际值为nil ExternallyTagged", t, func() {
  521. union := types.NewTypeUnion[Base](&St1{}, St2{})
  522. UseTypeUnionExternallyTagged(&union)
  523. var val []Base = []Base{
  524. nil,
  525. }
  526. data, err := ObjectToJSONEx(val)
  527. So(err, ShouldBeNil)
  528. ret, err := JSONToObjectEx[[]Base](data)
  529. So(err, ShouldBeNil)
  530. So(ret, ShouldResemble, val)
  531. })
  532. Convey("UnionType,但实际值为nil InternallyTagged", t, func() {
  533. union := types.NewTypeUnion[Base](&St1{}, St2{})
  534. UseTypeUnionInternallyTagged(&union, "Type")
  535. var val []Base = []Base{
  536. nil,
  537. }
  538. data, err := ObjectToJSONEx(val)
  539. So(err, ShouldBeNil)
  540. ret, err := JSONToObjectEx[[]Base](data)
  541. So(err, ShouldBeNil)
  542. So(ret, ShouldResemble, val)
  543. })
  544. }