config_test.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. package test
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "strings"
  6. "testing"
  7. jsoniter "github.com/json-iterator/go"
  8. "github.com/stretchr/testify/require"
  9. )
  10. func Test_use_number_for_unmarshal(t *testing.T) {
  11. should := require.New(t)
  12. api := jsoniter.Config{UseNumber: true}.Froze()
  13. var obj interface{}
  14. should.Nil(api.UnmarshalFromString("123", &obj))
  15. should.Equal(json.Number("123"), obj)
  16. }
  17. func Test_customize_float_marshal(t *testing.T) {
  18. should := require.New(t)
  19. json := jsoniter.Config{MarshalFloatWith6Digits: true}.Froze()
  20. str, err := json.MarshalToString(float32(1.23456789))
  21. should.Nil(err)
  22. should.Equal("1.234568", str)
  23. }
  24. func Test_max_depth(t *testing.T) {
  25. deepJSON := func(depth int) []byte {
  26. return []byte(strings.Repeat(`[`, depth) + strings.Repeat(`]`, depth))
  27. }
  28. tests := []struct {
  29. jsonDepth int
  30. cfgMaxDepth int
  31. expectedErr string
  32. }{
  33. // Test the default depth
  34. {jsonDepth: 10000, cfgMaxDepth: 0},
  35. {jsonDepth: 10001, cfgMaxDepth: 0, expectedErr: "max depth"},
  36. // Test max depth logic
  37. {jsonDepth: 5, cfgMaxDepth: 6},
  38. {jsonDepth: 5, cfgMaxDepth: 5},
  39. {jsonDepth: 5, cfgMaxDepth: 4, expectedErr: "max depth"},
  40. // Now try some larger values to figure out the limit
  41. {jsonDepth: 128000, cfgMaxDepth: -1},
  42. {jsonDepth: 512000, cfgMaxDepth: -1},
  43. {jsonDepth: 768000, cfgMaxDepth: -1},
  44. {jsonDepth: 860367, cfgMaxDepth: -1}, // largest value for jsoniter without stack overflow
  45. }
  46. for _, test := range tests {
  47. t.Run(fmt.Sprintf("jsonDepth:%v_cfgMaxDepth:%v", test.jsonDepth, test.cfgMaxDepth), func(t *testing.T) {
  48. if testing.Short() && test.jsonDepth >= 512000 {
  49. t.Skip("skipping in -short due to large input data")
  50. }
  51. should := require.New(t)
  52. cfg := jsoniter.Config{MaxDepth: test.cfgMaxDepth}.Froze()
  53. var val interface{}
  54. err := cfg.Unmarshal(deepJSON(test.jsonDepth), &val)
  55. if test.expectedErr != "" {
  56. should.Error(err)
  57. should.Contains(err.Error(), test.expectedErr)
  58. } else {
  59. should.NoError(err)
  60. }
  61. })
  62. }
  63. }
  64. func Test_customize_tag_key(t *testing.T) {
  65. type TestObject struct {
  66. Field string `orm:"field"`
  67. }
  68. should := require.New(t)
  69. json := jsoniter.Config{TagKey: "orm"}.Froze()
  70. str, err := json.MarshalToString(TestObject{"hello"})
  71. should.Nil(err)
  72. should.Equal(`{"field":"hello"}`, str)
  73. }
  74. func Test_read_large_number_as_interface(t *testing.T) {
  75. should := require.New(t)
  76. var val interface{}
  77. err := jsoniter.Config{UseNumber: true}.Froze().UnmarshalFromString(`123456789123456789123456789`, &val)
  78. should.Nil(err)
  79. output, err := jsoniter.MarshalToString(val)
  80. should.Nil(err)
  81. should.Equal(`123456789123456789123456789`, output)
  82. }
  83. type caseSensitiveStruct struct {
  84. A string `json:"a"`
  85. B string `json:"b,omitempty"`
  86. C *C `json:"C,omitempty"`
  87. }
  88. type C struct {
  89. D int64 `json:"D,omitempty"`
  90. E *E `json:"e,omitempty"`
  91. }
  92. type E struct {
  93. F string `json:"F,omitempty"`
  94. }
  95. func Test_CaseSensitive(t *testing.T) {
  96. should := require.New(t)
  97. testCases := []struct {
  98. input string
  99. expectedOutput string
  100. caseSensitive bool
  101. }{
  102. {
  103. input: `{"A":"foo","B":"bar"}`,
  104. expectedOutput: `{"a":"foo","b":"bar"}`,
  105. caseSensitive: false,
  106. },
  107. {
  108. input: `{"a":"foo","b":"bar"}`,
  109. expectedOutput: `{"a":"foo","b":"bar"}`,
  110. caseSensitive: true,
  111. },
  112. {
  113. input: `{"a":"foo","b":"bar","C":{"D":10}}`,
  114. expectedOutput: `{"a":"foo","b":"bar","C":{"D":10}}`,
  115. caseSensitive: true,
  116. },
  117. {
  118. input: `{"a":"foo","B":"bar","c":{"d":10}}`,
  119. expectedOutput: `{"a":"foo"}`,
  120. caseSensitive: true,
  121. },
  122. {
  123. input: `{"a":"foo","C":{"d":10}}`,
  124. expectedOutput: `{"a":"foo","C":{}}`,
  125. caseSensitive: true,
  126. },
  127. {
  128. input: `{"a":"foo","C":{"D":10,"e":{"f":"baz"}}}`,
  129. expectedOutput: `{"a":"foo","C":{"D":10,"e":{}}}`,
  130. caseSensitive: true,
  131. },
  132. {
  133. input: `{"a":"foo","C":{"D":10,"e":{"F":"baz"}}}`,
  134. expectedOutput: `{"a":"foo","C":{"D":10,"e":{"F":"baz"}}}`,
  135. caseSensitive: true,
  136. },
  137. {
  138. input: `{"A":"foo","c":{"d":10,"E":{"f":"baz"}}}`,
  139. expectedOutput: `{"a":"foo","C":{"D":10,"e":{"F":"baz"}}}`,
  140. caseSensitive: false,
  141. },
  142. }
  143. for _, tc := range testCases {
  144. val := caseSensitiveStruct{}
  145. err := jsoniter.Config{CaseSensitive: tc.caseSensitive}.Froze().UnmarshalFromString(tc.input, &val)
  146. should.Nil(err)
  147. output, err := jsoniter.MarshalToString(val)
  148. should.Nil(err)
  149. should.Equal(tc.expectedOutput, output)
  150. }
  151. }
  152. type structWithElevenFields struct {
  153. A string `json:"A,omitempty"`
  154. B string `json:"B,omitempty"`
  155. C string `json:"C,omitempty"`
  156. D string `json:"d,omitempty"`
  157. E string `json:"e,omitempty"`
  158. F string `json:"f,omitempty"`
  159. G string `json:"g,omitempty"`
  160. H string `json:"h,omitempty"`
  161. I string `json:"i,omitempty"`
  162. J string `json:"j,omitempty"`
  163. K string `json:"k,omitempty"`
  164. }
  165. func Test_CaseSensitive_MoreThanTenFields(t *testing.T) {
  166. should := require.New(t)
  167. testCases := []struct {
  168. input string
  169. expectedOutput string
  170. caseSensitive bool
  171. }{
  172. {
  173. input: `{"A":"1","B":"2","C":"3","d":"4","e":"5","f":"6","g":"7","h":"8","i":"9","j":"10","k":"11"}`,
  174. expectedOutput: `{"A":"1","B":"2","C":"3","d":"4","e":"5","f":"6","g":"7","h":"8","i":"9","j":"10","k":"11"}`,
  175. caseSensitive: true,
  176. },
  177. {
  178. input: `{"a":"1","b":"2","c":"3","D":"4","E":"5","F":"6"}`,
  179. expectedOutput: `{"A":"1","B":"2","C":"3","d":"4","e":"5","f":"6"}`,
  180. caseSensitive: false,
  181. },
  182. {
  183. input: `{"A":"1","b":"2","d":"4","E":"5"}`,
  184. expectedOutput: `{"A":"1","d":"4"}`,
  185. caseSensitive: true,
  186. },
  187. }
  188. for _, tc := range testCases {
  189. val := structWithElevenFields{}
  190. err := jsoniter.Config{CaseSensitive: tc.caseSensitive}.Froze().UnmarshalFromString(tc.input, &val)
  191. should.Nil(err)
  192. output, err := jsoniter.MarshalToString(val)
  193. should.Nil(err)
  194. should.Equal(tc.expectedOutput, output)
  195. }
  196. }
  197. type onlyTaggedFieldStruct struct {
  198. A string `json:"a"`
  199. B string
  200. FSimpl F `json:"f_simpl"`
  201. ISimpl I
  202. FPtr *F `json:"f_ptr"`
  203. IPtr *I
  204. F
  205. *I
  206. }
  207. type F struct {
  208. G string `json:"g"`
  209. H string
  210. }
  211. type I struct {
  212. J string `json:"j"`
  213. K string
  214. }
  215. func Test_OnlyTaggedField(t *testing.T) {
  216. should := require.New(t)
  217. obj := onlyTaggedFieldStruct{
  218. A: "a",
  219. B: "b",
  220. FSimpl: F{G: "g", H: "h"},
  221. ISimpl: I{J: "j", K: "k"},
  222. FPtr: &F{G: "g", H: "h"},
  223. IPtr: &I{J: "j", K: "k"},
  224. F: F{G: "g", H: "h"},
  225. I: &I{J: "j", K: "k"},
  226. }
  227. output, err := jsoniter.Config{OnlyTaggedField: true}.Froze().Marshal(obj)
  228. should.Nil(err)
  229. m := make(map[string]interface{})
  230. err = jsoniter.Unmarshal(output, &m)
  231. should.Nil(err)
  232. should.Equal(map[string]interface{}{
  233. "a": "a",
  234. "f_simpl": map[string]interface{}{
  235. "g": "g",
  236. },
  237. "f_ptr": map[string]interface{}{
  238. "g": "g",
  239. },
  240. "g": "g",
  241. "j": "j",
  242. }, m)
  243. }