jsoniter_nested_test.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. package misc_tests
  2. import (
  3. "encoding/json"
  4. "github.com/json-iterator/go"
  5. "reflect"
  6. "strings"
  7. "testing"
  8. )
  9. type Level1 struct {
  10. Hello []Level2
  11. }
  12. type Level2 struct {
  13. World string
  14. }
  15. func Test_deep_nested(t *testing.T) {
  16. type unstructured interface{}
  17. testcases := []struct {
  18. name string
  19. data []byte
  20. expectError string
  21. }{
  22. {
  23. name: "array under maxDepth",
  24. data: []byte(`{"a":` + strings.Repeat(`[`, 10000-1) + strings.Repeat(`]`, 10000-1) + `}`),
  25. expectError: "",
  26. },
  27. {
  28. name: "array over maxDepth",
  29. data: []byte(`{"a":` + strings.Repeat(`[`, 10000) + strings.Repeat(`]`, 10000) + `}`),
  30. expectError: "max depth",
  31. },
  32. {
  33. name: "object under maxDepth",
  34. data: []byte(`{"a":` + strings.Repeat(`{"a":`, 10000-1) + `0` + strings.Repeat(`}`, 10000-1) + `}`),
  35. expectError: "",
  36. },
  37. {
  38. name: "object over maxDepth",
  39. data: []byte(`{"a":` + strings.Repeat(`{"a":`, 10000) + `0` + strings.Repeat(`}`, 10000) + `}`),
  40. expectError: "max depth",
  41. },
  42. }
  43. targets := []struct {
  44. name string
  45. new func() interface{}
  46. }{
  47. {
  48. name: "unstructured",
  49. new: func() interface{} {
  50. var v interface{}
  51. return &v
  52. },
  53. },
  54. {
  55. name: "typed named field",
  56. new: func() interface{} {
  57. v := struct {
  58. A interface{} `json:"a"`
  59. }{}
  60. return &v
  61. },
  62. },
  63. {
  64. name: "typed missing field",
  65. new: func() interface{} {
  66. v := struct {
  67. B interface{} `json:"b"`
  68. }{}
  69. return &v
  70. },
  71. },
  72. {
  73. name: "typed 1 field",
  74. new: func() interface{} {
  75. v := struct {
  76. A interface{} `json:"a"`
  77. }{}
  78. return &v
  79. },
  80. },
  81. {
  82. name: "typed 2 field",
  83. new: func() interface{} {
  84. v := struct {
  85. A interface{} `json:"a"`
  86. B interface{} `json:"b"`
  87. }{}
  88. return &v
  89. },
  90. },
  91. {
  92. name: "typed 3 field",
  93. new: func() interface{} {
  94. v := struct {
  95. A interface{} `json:"a"`
  96. B interface{} `json:"b"`
  97. C interface{} `json:"c"`
  98. }{}
  99. return &v
  100. },
  101. },
  102. {
  103. name: "typed 4 field",
  104. new: func() interface{} {
  105. v := struct {
  106. A interface{} `json:"a"`
  107. B interface{} `json:"b"`
  108. C interface{} `json:"c"`
  109. D interface{} `json:"d"`
  110. }{}
  111. return &v
  112. },
  113. },
  114. {
  115. name: "typed 5 field",
  116. new: func() interface{} {
  117. v := struct {
  118. A interface{} `json:"a"`
  119. B interface{} `json:"b"`
  120. C interface{} `json:"c"`
  121. D interface{} `json:"d"`
  122. E interface{} `json:"e"`
  123. }{}
  124. return &v
  125. },
  126. },
  127. {
  128. name: "typed 6 field",
  129. new: func() interface{} {
  130. v := struct {
  131. A interface{} `json:"a"`
  132. B interface{} `json:"b"`
  133. C interface{} `json:"c"`
  134. D interface{} `json:"d"`
  135. E interface{} `json:"e"`
  136. F interface{} `json:"f"`
  137. }{}
  138. return &v
  139. },
  140. },
  141. {
  142. name: "typed 7 field",
  143. new: func() interface{} {
  144. v := struct {
  145. A interface{} `json:"a"`
  146. B interface{} `json:"b"`
  147. C interface{} `json:"c"`
  148. D interface{} `json:"d"`
  149. E interface{} `json:"e"`
  150. F interface{} `json:"f"`
  151. G interface{} `json:"g"`
  152. }{}
  153. return &v
  154. },
  155. },
  156. {
  157. name: "typed 8 field",
  158. new: func() interface{} {
  159. v := struct {
  160. A interface{} `json:"a"`
  161. B interface{} `json:"b"`
  162. C interface{} `json:"c"`
  163. D interface{} `json:"d"`
  164. E interface{} `json:"e"`
  165. F interface{} `json:"f"`
  166. G interface{} `json:"g"`
  167. H interface{} `json:"h"`
  168. }{}
  169. return &v
  170. },
  171. },
  172. {
  173. name: "typed 9 field",
  174. new: func() interface{} {
  175. v := struct {
  176. A interface{} `json:"a"`
  177. B interface{} `json:"b"`
  178. C interface{} `json:"c"`
  179. D interface{} `json:"d"`
  180. E interface{} `json:"e"`
  181. F interface{} `json:"f"`
  182. G interface{} `json:"g"`
  183. H interface{} `json:"h"`
  184. I interface{} `json:"i"`
  185. }{}
  186. return &v
  187. },
  188. },
  189. {
  190. name: "typed 10 field",
  191. new: func() interface{} {
  192. v := struct {
  193. A interface{} `json:"a"`
  194. B interface{} `json:"b"`
  195. C interface{} `json:"c"`
  196. D interface{} `json:"d"`
  197. E interface{} `json:"e"`
  198. F interface{} `json:"f"`
  199. G interface{} `json:"g"`
  200. H interface{} `json:"h"`
  201. I interface{} `json:"i"`
  202. J interface{} `json:"j"`
  203. }{}
  204. return &v
  205. },
  206. },
  207. {
  208. name: "typed 11 field",
  209. new: func() interface{} {
  210. v := struct {
  211. A interface{} `json:"a"`
  212. B interface{} `json:"b"`
  213. C interface{} `json:"c"`
  214. D interface{} `json:"d"`
  215. E interface{} `json:"e"`
  216. F interface{} `json:"f"`
  217. G interface{} `json:"g"`
  218. H interface{} `json:"h"`
  219. I interface{} `json:"i"`
  220. J interface{} `json:"j"`
  221. K interface{} `json:"k"`
  222. }{}
  223. return &v
  224. },
  225. },
  226. }
  227. for _, tc := range testcases {
  228. t.Run(tc.name, func(t *testing.T) {
  229. for _, target := range targets {
  230. t.Run(target.name, func(t *testing.T) {
  231. err := jsoniter.Unmarshal(tc.data, target.new())
  232. if len(tc.expectError) == 0 {
  233. if err != nil {
  234. t.Errorf("unexpected error: %v", err)
  235. }
  236. } else {
  237. if err == nil {
  238. t.Errorf("expected error, got none")
  239. } else if !strings.Contains(err.Error(), tc.expectError) {
  240. t.Errorf("expected error containing '%s', got: %v", tc.expectError, err)
  241. }
  242. }
  243. })
  244. }
  245. })
  246. }
  247. }
  248. func Test_nested(t *testing.T) {
  249. iter := jsoniter.ParseString(jsoniter.ConfigDefault, `{"hello": [{"world": "value1"}, {"world": "value2"}]}`)
  250. l1 := Level1{}
  251. for l1Field := iter.ReadObject(); l1Field != ""; l1Field = iter.ReadObject() {
  252. switch l1Field {
  253. case "hello":
  254. l2Array := []Level2{}
  255. for iter.ReadArray() {
  256. l2 := Level2{}
  257. for l2Field := iter.ReadObject(); l2Field != ""; l2Field = iter.ReadObject() {
  258. switch l2Field {
  259. case "world":
  260. l2.World = iter.ReadString()
  261. default:
  262. iter.ReportError("bind l2", "unexpected field: "+l2Field)
  263. }
  264. }
  265. l2Array = append(l2Array, l2)
  266. }
  267. l1.Hello = l2Array
  268. default:
  269. iter.ReportError("bind l1", "unexpected field: "+l1Field)
  270. }
  271. }
  272. if !reflect.DeepEqual(l1, Level1{
  273. Hello: []Level2{
  274. {World: "value1"},
  275. {World: "value2"},
  276. },
  277. }) {
  278. t.Fatal(l1)
  279. }
  280. }
  281. func Benchmark_jsoniter_nested(b *testing.B) {
  282. for n := 0; n < b.N; n++ {
  283. iter := jsoniter.ParseString(jsoniter.ConfigDefault, `{"hello": [{"world": "value1"}, {"world": "value2"}]}`)
  284. l1 := Level1{}
  285. for l1Field := iter.ReadObject(); l1Field != ""; l1Field = iter.ReadObject() {
  286. switch l1Field {
  287. case "hello":
  288. l1.Hello = readLevel1Hello(iter)
  289. default:
  290. iter.Skip()
  291. }
  292. }
  293. }
  294. }
  295. func readLevel1Hello(iter *jsoniter.Iterator) []Level2 {
  296. l2Array := make([]Level2, 0, 2)
  297. for iter.ReadArray() {
  298. l2 := Level2{}
  299. for l2Field := iter.ReadObject(); l2Field != ""; l2Field = iter.ReadObject() {
  300. switch l2Field {
  301. case "world":
  302. l2.World = iter.ReadString()
  303. default:
  304. iter.Skip()
  305. }
  306. }
  307. l2Array = append(l2Array, l2)
  308. }
  309. return l2Array
  310. }
  311. func Benchmark_json_nested(b *testing.B) {
  312. for n := 0; n < b.N; n++ {
  313. l1 := Level1{}
  314. json.Unmarshal([]byte(`{"hello": [{"world": "value1"}, {"world": "value2"}]}`), &l1)
  315. }
  316. }