tjson.nim 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #[
  2. Note: Macro tests are in tests/stdlib/tjsonmacro.nim
  3. ]#
  4. import std/[json,parsejson,strutils,streams]
  5. let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd", "c": "\ud83c\udf83", "d": "\u00E6"}"""
  6. # nil passthrough
  7. doAssert(testJson{"doesnt_exist"}{"anything"}.isNil)
  8. testJson{["e", "f"]} = %true
  9. doAssert(testJson["e"]["f"].bval)
  10. # make sure UTF-16 decoding works.
  11. doAssert(testJson["c"].str == "🎃")
  12. doAssert(testJson["d"].str == "æ")
  13. # make sure no memory leek when parsing invalid string
  14. let startMemory = getOccupiedMem()
  15. for i in 0 .. 10000:
  16. try:
  17. discard parseJson"""{ invalid"""
  18. except:
  19. discard
  20. # memory diff should less than 4M
  21. doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024)
  22. # test `$`
  23. let stringified = $testJson
  24. let parsedAgain = parseJson(stringified)
  25. doAssert(parsedAgain["b"].str == "asd")
  26. parsedAgain["abc"] = %5
  27. doAssert parsedAgain["abc"].num == 5
  28. # Bounds checking
  29. when compileOption("boundChecks"):
  30. try:
  31. let a = testJson["a"][9]
  32. doAssert(false, "IndexDefect not thrown")
  33. except IndexDefect:
  34. discard
  35. try:
  36. let a = testJson["a"][-1]
  37. doAssert(false, "IndexDefect not thrown")
  38. except IndexDefect:
  39. discard
  40. try:
  41. doAssert(testJson["a"][0].num == 1, "Index doesn't correspond to its value")
  42. except:
  43. doAssert(false, "IndexDefect thrown for valid index")
  44. doAssert(testJson{"b"}.getStr() == "asd", "Couldn't fetch a singly nested key with {}")
  45. doAssert(isNil(testJson{"nonexistent"}), "Non-existent keys should return nil")
  46. doAssert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
  47. doAssert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
  48. doAssert(testJson{"a"} == parseJson"[1, 2, 3, 4]", "Didn't return a non-JObject when there was one to be found")
  49. doAssert(isNil(parseJson("[1, 2, 3]"){"foo"}), "Indexing directly into a list should return nil")
  50. # Generator:
  51. var j = %* [{"name": "John", "age": 30}, {"name": "Susan", "age": 31}]
  52. doAssert j == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
  53. var j2 = %*
  54. [
  55. {
  56. "name": "John",
  57. "age": 30
  58. },
  59. {
  60. "name": "Susan",
  61. "age": 31
  62. }
  63. ]
  64. doAssert j2 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
  65. var name = "John"
  66. let herAge = 30
  67. const hisAge = 31
  68. var j3 = %*
  69. [ {"name": "John"
  70. , "age": herAge
  71. }
  72. , {"name": "Susan"
  73. , "age": hisAge
  74. }
  75. ]
  76. doAssert j3 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
  77. var j4 = %*{"test": nil}
  78. doAssert j4 == %{"test": newJNull()}
  79. let seqOfNodes = @[%1, %2]
  80. let jSeqOfNodes = %seqOfNodes
  81. doAssert(jSeqOfNodes[1].num == 2)
  82. type MyObj = object
  83. a, b: int
  84. s: string
  85. f32: float32
  86. f64: float64
  87. next: ref MyObj
  88. var m: MyObj
  89. m.s = "hi"
  90. m.a = 5
  91. let jMyObj = %m
  92. doAssert(jMyObj["a"].num == 5)
  93. doAssert(jMyObj["s"].str == "hi")
  94. # Test loading of file.
  95. when not defined(js):
  96. var parsed = parseFile("tests/testdata/jsontest.json")
  97. try:
  98. discard parsed["key2"][12123]
  99. doAssert(false)
  100. except IndexDefect: doAssert(true)
  101. var parsed2 = parseFile("tests/testdata/jsontest2.json")
  102. doAssert(parsed2{"repository", "description"}.str ==
  103. "IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}")
  104. doAssert escapeJsonUnquoted("\10Foo🎃barÄ") == "\\nFoo🎃barÄ"
  105. doAssert escapeJsonUnquoted("\0\7\20") == "\\u0000\\u0007\\u0014" # for #7887
  106. doAssert escapeJson("\10Foo🎃barÄ") == "\"\\nFoo🎃barÄ\""
  107. doAssert escapeJson("\0\7\20") == "\"\\u0000\\u0007\\u0014\"" # for #7887
  108. # Test with extra data
  109. when not defined(js):
  110. try:
  111. discard parseJson("123 456")
  112. doAssert(false)
  113. except JsonParsingError:
  114. doAssert getCurrentExceptionMsg().contains(errorMessages[errEofExpected])
  115. try:
  116. discard parseFile("tests/testdata/jsonwithextradata.json")
  117. doAssert(false)
  118. except JsonParsingError:
  119. doAssert getCurrentExceptionMsg().contains(errorMessages[errEofExpected])
  120. # bug #6438
  121. doAssert($ %*[] == "[]")
  122. doAssert($ %*{} == "{}")
  123. doAssert(not compiles(%{"error": "No messages"}))
  124. # bug #9111
  125. block:
  126. type
  127. Bar = string
  128. Foo = object
  129. a: int
  130. b: Bar
  131. let
  132. js = """{"a": 123, "b": "abc"}""".parseJson
  133. foo = js.to Foo
  134. doAssert(foo.b == "abc")
  135. # Generate constructors for range[T] types
  136. block:
  137. type
  138. Q1 = range[0'u8 .. 50'u8]
  139. Q2 = range[0'u16 .. 50'u16]
  140. Q3 = range[0'u32 .. 50'u32]
  141. Q4 = range[0'i8 .. 50'i8]
  142. Q5 = range[0'i16 .. 50'i16]
  143. Q6 = range[0'i32 .. 50'i32]
  144. Q7 = range[0'f32 .. 50'f32]
  145. Q8 = range[0'f64 .. 50'f64]
  146. Q9 = range[0 .. 50]
  147. X = object
  148. m1: Q1
  149. m2: Q2
  150. m3: Q3
  151. m4: Q4
  152. m5: Q5
  153. m6: Q6
  154. m7: Q7
  155. m8: Q8
  156. m9: Q9
  157. let obj = X(
  158. m1: Q1(42),
  159. m2: Q2(42),
  160. m3: Q3(42),
  161. m4: Q4(42),
  162. m5: Q5(42),
  163. m6: Q6(42),
  164. m7: Q7(42),
  165. m8: Q8(42),
  166. m9: Q9(42)
  167. )
  168. doAssert(obj == to(%obj, type(obj)))
  169. when not defined(js):
  170. const fragments = """[1,2,3] {"hi":3} 12 [] """
  171. var res = ""
  172. for x in parseJsonFragments(newStringStream(fragments)):
  173. res.add($x)
  174. res.add " "
  175. doAssert res == fragments
  176. # test isRefSkipDistinct
  177. type
  178. MyRef = ref object
  179. MyObject = object
  180. MyDistinct = distinct MyRef
  181. MyOtherDistinct = distinct MyRef
  182. var x0: ref int
  183. var x1: MyRef
  184. var x2: MyObject
  185. var x3: MyDistinct
  186. var x4: MyOtherDistinct
  187. doAssert isRefSkipDistinct(x0)
  188. doAssert isRefSkipDistinct(x1)
  189. doAssert not isRefSkipDistinct(x2)
  190. doAssert isRefSkipDistinct(x3)
  191. doAssert isRefSkipDistinct(x4)
  192. doAssert isRefSkipDistinct(ref int)
  193. doAssert isRefSkipDistinct(MyRef)
  194. doAssert not isRefSkipDistinct(MyObject)
  195. doAssert isRefSkipDistinct(MyDistinct)
  196. doAssert isRefSkipDistinct(MyOtherDistinct)
  197. let x = parseJson("9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999")
  198. doAssert x.kind == JString