json_spec.lua (12844B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 4 local clear = n.clear 5 local exec_lua = n.exec_lua 6 local eq = t.eq 7 local pcall_err = t.pcall_err 8 9 describe('vim.json.decode()', function() 10 before_each(function() 11 clear() 12 end) 13 14 it('parses null, true, false', function() 15 eq(vim.NIL, exec_lua([[return vim.json.decode('null')]])) 16 eq(true, exec_lua([[return vim.json.decode('true')]])) 17 eq(false, exec_lua([[return vim.json.decode('false')]])) 18 end) 19 20 it('validation', function() 21 eq( 22 'Expected object key string but found invalid token at character 2', 23 pcall_err(exec_lua, [[return vim.json.decode('{a:"b"}')]]) 24 ) 25 end) 26 27 it('options', function() 28 local jsonstr = '{"arr":[1,2,null],"bar":[3,7],"foo":{"a":"b"},"baz":null}' 29 eq({ 30 arr = { 1, 2, vim.NIL }, 31 bar = { 3, 7 }, 32 baz = vim.NIL, 33 foo = { a = 'b' }, 34 }, exec_lua([[return vim.json.decode(..., {})]], jsonstr)) 35 eq( 36 { 37 arr = { 1, 2, vim.NIL }, 38 bar = { 3, 7 }, 39 baz = vim.NIL, 40 foo = { a = 'b' }, 41 }, 42 exec_lua( 43 [[return vim.json.decode(..., { luanil = { array = false, object = false } })]], 44 jsonstr 45 ) 46 ) 47 eq({ 48 arr = { 1, 2, vim.NIL }, 49 bar = { 3, 7 }, 50 -- baz = nil, 51 foo = { a = 'b' }, 52 }, exec_lua([[return vim.json.decode(..., { luanil = { object = true } })]], jsonstr)) 53 eq({ 54 arr = { 1, 2 }, 55 bar = { 3, 7 }, 56 baz = vim.NIL, 57 foo = { a = 'b' }, 58 }, exec_lua([[return vim.json.decode(..., { luanil = { array = true } })]], jsonstr)) 59 eq( 60 { 61 arr = { 1, 2 }, 62 bar = { 3, 7 }, 63 -- baz = nil, 64 foo = { a = 'b' }, 65 }, 66 exec_lua( 67 [[return vim.json.decode(..., { luanil = { array = true, object = true } })]], 68 jsonstr 69 ) 70 ) 71 end) 72 73 it('parses integer numbers', function() 74 eq(100000, exec_lua([[return vim.json.decode('100000')]])) 75 eq(-100000, exec_lua([[return vim.json.decode('-100000')]])) 76 eq(100000, exec_lua([[return vim.json.decode(' 100000 ')]])) 77 eq(-100000, exec_lua([[return vim.json.decode(' -100000 ')]])) 78 eq(0, exec_lua([[return vim.json.decode('0')]])) 79 eq(0, exec_lua([[return vim.json.decode('-0')]])) 80 eq(3053700806959403, exec_lua([[return vim.json.decode('3053700806959403')]])) 81 end) 82 83 it('parses floating-point numbers', function() 84 -- This behavior differs from vim.fn.json_decode, which return '100000.0' 85 eq('100000', exec_lua([[return tostring(vim.json.decode('100000.0'))]])) 86 eq(100000.5, exec_lua([[return vim.json.decode('100000.5')]])) 87 eq(-100000.5, exec_lua([[return vim.json.decode('-100000.5')]])) 88 eq(-100000.5e50, exec_lua([[return vim.json.decode('-100000.5e50')]])) 89 eq(100000.5e50, exec_lua([[return vim.json.decode('100000.5e50')]])) 90 eq(100000.5e50, exec_lua([[return vim.json.decode('100000.5e+50')]])) 91 eq(-100000.5e-50, exec_lua([[return vim.json.decode('-100000.5e-50')]])) 92 eq(100000.5e-50, exec_lua([[return vim.json.decode('100000.5e-50')]])) 93 eq(100000e-50, exec_lua([[return vim.json.decode('100000e-50')]])) 94 eq(0.5, exec_lua([[return vim.json.decode('0.5')]])) 95 eq(0.005, exec_lua([[return vim.json.decode('0.005')]])) 96 eq(0.005, exec_lua([[return vim.json.decode('0.00500')]])) 97 eq(0.5, exec_lua([[return vim.json.decode('0.00500e+002')]])) 98 eq(0.00005, exec_lua([[return vim.json.decode('0.00500e-002')]])) 99 100 eq(-0.0, exec_lua([[return vim.json.decode('-0.0')]])) 101 eq(-0.0, exec_lua([[return vim.json.decode('-0.0e0')]])) 102 eq(-0.0, exec_lua([[return vim.json.decode('-0.0e+0')]])) 103 eq(-0.0, exec_lua([[return vim.json.decode('-0.0e-0')]])) 104 eq(-0.0, exec_lua([[return vim.json.decode('-0e-0')]])) 105 eq(-0.0, exec_lua([[return vim.json.decode('-0e-2')]])) 106 eq(-0.0, exec_lua([[return vim.json.decode('-0e+2')]])) 107 108 eq(0.0, exec_lua([[return vim.json.decode('0.0')]])) 109 eq(0.0, exec_lua([[return vim.json.decode('0.0e0')]])) 110 eq(0.0, exec_lua([[return vim.json.decode('0.0e+0')]])) 111 eq(0.0, exec_lua([[return vim.json.decode('0.0e-0')]])) 112 eq(0.0, exec_lua([[return vim.json.decode('0e-0')]])) 113 eq(0.0, exec_lua([[return vim.json.decode('0e-2')]])) 114 eq(0.0, exec_lua([[return vim.json.decode('0e+2')]])) 115 end) 116 117 it('parses containers', function() 118 eq({ 1 }, exec_lua([[return vim.json.decode('[1]')]])) 119 eq({ vim.NIL, 1 }, exec_lua([[return vim.json.decode('[null, 1]')]])) 120 eq({ ['1'] = 2 }, exec_lua([[return vim.json.decode('{"1": 2}')]])) 121 eq( 122 { ['1'] = 2, ['3'] = { { ['4'] = { ['5'] = { {}, 1 } } } } }, 123 exec_lua([[return vim.json.decode('{"1": 2, "3": [{"4": {"5": [ [], 1]}}]}')]]) 124 ) 125 -- Empty string is a valid key. #20757 126 eq({ [''] = 42 }, exec_lua([[return vim.json.decode('{"": 42}')]])) 127 end) 128 129 it('parses strings properly', function() 130 eq('\n', exec_lua([=[return vim.json.decode([["\n"]])]=])) 131 eq('', exec_lua([=[return vim.json.decode([[""]])]=])) 132 eq('\\/"\t\b\n\r\f', exec_lua([=[return vim.json.decode([["\\\/\"\t\b\n\r\f"]])]=])) 133 eq('/a', exec_lua([=[return vim.json.decode([["\/a"]])]=])) 134 -- Unicode characters: 2-byte, 3-byte 135 eq('«', exec_lua([=[return vim.json.decode([["«"]])]=])) 136 eq('ફ', exec_lua([=[return vim.json.decode([["ફ"]])]=])) 137 end) 138 139 it('parses surrogate pairs properly', function() 140 eq('\240\144\128\128', exec_lua([[return vim.json.decode('"\\uD800\\uDC00"')]])) 141 end) 142 143 it('accepts all spaces in every position where space may be put', function() 144 local s = 145 ' \t\n\r \t\r\n \n\t\r \n\r\t \r\t\n \r\n\t\t \n\r\t \r\n\t\n \r\t\n\r \t\r \n\t\r\n \n \t\r\n \r\t\n\t \r\n\t\r \n\r \t\n\r\t \r \t\n\r \n\t\r\t \n\r\t\n \r\n \t\r\n\t' 146 local str = ('%s{%s"key"%s:%s[%s"val"%s,%s"val2"%s]%s,%s"key2"%s:%s1%s}%s'):gsub('%%s', s) 147 eq({ key = { 'val', 'val2' }, key2 = 1 }, exec_lua([[return vim.json.decode(...)]], str)) 148 end) 149 150 it('skip_comments', function() 151 eq({}, exec_lua([[return vim.json.decode('{//comment\n}', { skip_comments = true })]])) 152 eq({}, exec_lua([[return vim.json.decode('{//comment\r\n}', { skip_comments = true })]])) 153 eq( 154 'test // /* */ string', 155 exec_lua( 156 [[return vim.json.decode('"test // /* */ string"//comment', { skip_comments = true })]] 157 ) 158 ) 159 eq( 160 {}, 161 exec_lua([[return vim.json.decode('{/* A multi-line\ncomment*/}', { skip_comments = true })]]) 162 ) 163 eq( 164 { a = 1 }, 165 exec_lua([[return vim.json.decode('{"a" /* Comment */: 1}', { skip_comments = true })]]) 166 ) 167 eq( 168 { a = 1 }, 169 exec_lua([[return vim.json.decode('{"a": /* Comment */ 1}', { skip_comments = true })]]) 170 ) 171 eq({}, exec_lua([[return vim.json.decode('/*first*//*second*/{}', { skip_comments = true })]])) 172 eq( 173 'Expected the end but found unclosed multi-line comment at character 13', 174 pcall_err(exec_lua, [[return vim.json.decode('{}/*Unclosed', { skip_comments = true })]]) 175 ) 176 eq( 177 'Expected comma or object end but found T_INTEGER at character 12', 178 pcall_err(exec_lua, [[return vim.json.decode('{"a":1/*x*/0}', { skip_comments = true })]]) 179 ) 180 end) 181 end) 182 183 describe('vim.json.encode()', function() 184 before_each(function() 185 clear() 186 end) 187 188 it('escape_slash', function() 189 -- With slash 190 eq('"Test\\/"', exec_lua([[return vim.json.encode('Test/', { escape_slash = true })]])) 191 eq( 192 'Test/', 193 exec_lua([[return vim.json.decode(vim.json.encode('Test/', { escape_slash = true }))]]) 194 ) 195 196 -- Without slash 197 eq('"Test/"', exec_lua([[return vim.json.encode('Test/')]])) 198 eq('"Test/"', exec_lua([[return vim.json.encode('Test/', {})]])) 199 eq('"Test/"', exec_lua([[return vim.json.encode('Test/', { _invalid = true })]])) 200 eq('"Test/"', exec_lua([[return vim.json.encode('Test/', { escape_slash = false })]])) 201 eq( 202 '"Test/"', 203 exec_lua([[return vim.json.encode('Test/', { _invalid = true, escape_slash = false })]]) 204 ) 205 eq( 206 'Test/', 207 exec_lua([[return vim.json.decode(vim.json.encode('Test/', { escape_slash = false }))]]) 208 ) 209 210 -- Checks for for global side-effects 211 eq( 212 '"Test/"', 213 exec_lua([[ 214 vim.json.encode('Test/', { escape_slash = true }) 215 return vim.json.encode('Test/') 216 ]]) 217 ) 218 eq( 219 '"Test\\/"', 220 exec_lua([[ 221 vim.json.encode('Test/', { escape_slash = false }) 222 return vim.json.encode('Test/', { escape_slash = true }) 223 ]]) 224 ) 225 end) 226 227 it('indent', function() 228 eq('"Test"', exec_lua([[return vim.json.encode('Test', { indent = " " })]])) 229 eq('[]', exec_lua([[return vim.json.encode({}, { indent = " " })]])) 230 eq('{}', exec_lua([[return vim.json.encode(vim.empty_dict(), { indent = " " })]])) 231 eq( 232 '[\n {\n "a": "a"\n },\n {\n "b": "b"\n }\n]', 233 exec_lua([[return vim.json.encode({ { a = "a" }, { b = "b" } }, { indent = " " })]]) 234 ) 235 eq( 236 '{\n "a": {\n "b": 1\n }\n}', 237 exec_lua([[return vim.json.encode({ a = { b = 1 } }, { indent = " " })]]) 238 ) 239 eq( 240 '[{"a":"a"},{"b":"b"}]', 241 exec_lua([[return vim.json.encode({ { a = "a" }, { b = "b" } }, { indent = "" })]]) 242 ) 243 eq( 244 '[\n [\n 1,\n 2\n ],\n [\n 3,\n 4\n ]\n]', 245 exec_lua([[return vim.json.encode({ { 1, 2 }, { 3, 4 } }, { indent = " " })]]) 246 ) 247 eq( 248 '{\nabc"a": {\nabcabc"b": 1\nabc}\n}', 249 exec_lua([[return vim.json.encode({ a = { b = 1 } }, { indent = "abc" })]]) 250 ) 251 252 -- Checks for for global side-effects 253 eq( 254 '[{"a":"a"},{"b":"b"}]', 255 exec_lua([[ 256 vim.json.encode('', { indent = " " }) 257 return vim.json.encode({ { a = "a" }, { b = "b" } }) 258 ]]) 259 ) 260 end) 261 262 it('sort_keys', function() 263 eq('"string"', exec_lua([[return vim.json.encode('string', { sort_keys = true })]])) 264 eq('[]', exec_lua([[return vim.json.encode({}, { sort_keys = true })]])) 265 eq('{}', exec_lua([[return vim.json.encode(vim.empty_dict(), { sort_keys = true })]])) 266 eq( 267 '{"$":0,"%":0,"1":0,"4":0,"a":0,"ab":0,"b":0}', 268 exec_lua( 269 [[return vim.json.encode({ a = 0, b = 0, ab = 0, [1] = 0, ["$"] = 0, [4] = 0, ["%"] = 0 }, { sort_keys = true })]] 270 ) 271 ) 272 eq( 273 '{"aa":1,"ab":2,"ba":3,"bc":4,"cc":5}', 274 exec_lua( 275 [[return vim.json.encode({ aa = 1, ba = 3, ab = 2, bc = 4, cc = 5 }, { sort_keys = true })]] 276 ) 277 ) 278 eq( 279 '{"a":{"a":1,"b":2,"c":3},"b":{"a":{"a":0,"b":0},"b":{"a":0,"b":0}},"c":0}', 280 exec_lua( 281 [[return vim.json.encode({ a = { b = 2, a = 1, c = 3 }, c = 0, b = { b = { a = 0, b = 0 }, a = { a = 0, b = 0 } } }, { sort_keys = true })]] 282 ) 283 ) 284 eq( 285 '[{"1":0,"4":0,"a":0,"b":0},{"10":0,"5":0,"f":0,"x":0},{"-2":0,"2":0,"c":0,"d":0}]', 286 exec_lua([[return vim.json.encode({ 287 { a = 0, [1] = 0, [4] = 0, b = 0 }, 288 { f = 0, [5] = 0, [10] = 0, x = 0 }, 289 { c = 0, [-2] = 0, [2] = 0, d = 0 }, 290 }, { sort_keys = true })]]) 291 ) 292 eq( 293 '{"a":2,"ß":3,"é":1,"中":4}', 294 exec_lua( 295 [[return vim.json.encode({ ["é"] = 1, ["a"] = 2, ["ß"] = 3, ["中"] = 4 }, { sort_keys = true })]] 296 ) 297 ) 298 end) 299 300 it('dumps strings', function() 301 eq('"Test"', exec_lua([[return vim.json.encode('Test')]])) 302 eq('""', exec_lua([[return vim.json.encode('')]])) 303 eq('"\\t"', exec_lua([[return vim.json.encode('\t')]])) 304 eq('"\\n"', exec_lua([[return vim.json.encode('\n')]])) 305 -- vim.fn.json_encode return \\u001B 306 eq('"\\u001b"', exec_lua([[return vim.json.encode('\27')]])) 307 eq('"þÿþ"', exec_lua([[return vim.json.encode('þÿþ')]])) 308 end) 309 310 it('dumps numbers', function() 311 eq('0', exec_lua([[return vim.json.encode(0)]])) 312 eq('10', exec_lua([[return vim.json.encode(10)]])) 313 eq('-10', exec_lua([[return vim.json.encode(-10)]])) 314 end) 315 316 it('dumps floats', function() 317 eq('3053700806959403', exec_lua([[return vim.json.encode(3053700806959403)]])) 318 eq('10.5', exec_lua([[return vim.json.encode(10.5)]])) 319 eq('-10.5', exec_lua([[return vim.json.encode(-10.5)]])) 320 eq('-1e-05', exec_lua([[return vim.json.encode(-1e-5)]])) 321 end) 322 323 it('dumps lists', function() 324 eq('[]', exec_lua([[return vim.json.encode({})]])) 325 eq('[[]]', exec_lua([[return vim.json.encode({{}})]])) 326 eq('[[],[]]', exec_lua([[return vim.json.encode({{}, {}})]])) 327 end) 328 329 it('dumps dictionaries', function() 330 eq('{}', exec_lua([[return vim.json.encode(vim.empty_dict())]])) 331 eq('{"d":[]}', exec_lua([[return vim.json.encode({d={}})]])) 332 -- Empty string is a valid key. #20757 333 eq('{"":42}', exec_lua([[return vim.json.encode({['']=42})]])) 334 end) 335 336 it('dumps vim.NIL', function() 337 eq('null', exec_lua([[return vim.json.encode(vim.NIL)]])) 338 end) 339 end)