diff options
| author | leaf corcoran <leafot@gmail.com> | 2019-09-22 13:21:45 -0700 |
|---|---|---|
| committer | leaf <leafot@gmail.com> | 2020-04-25 14:24:18 -0700 |
| commit | 461c7ef23a49062d4b1bf0e1afb3be294d007861 (patch) | |
| tree | 36b4e13561dd53d40bd87676c9aaf3fb5f1eea74 | |
| parent | dbcfb92e12e9016060d1907a2556cc61e82f467d (diff) | |
| download | lua-cjson-461c7ef23a49062d4b1bf0e1afb3be294d007861.tar.gz lua-cjson-461c7ef23a49062d4b1bf0e1afb3be294d007861.tar.bz2 lua-cjson-461c7ef23a49062d4b1bf0e1afb3be294d007861.zip | |
write sort_json, use it on perl tests to prevent hash table ordering failures
| -rw-r--r-- | tests/agentzh.t | 13 | ||||
| -rw-r--r-- | tests/sort_json.lua | 61 |
2 files changed, 69 insertions, 5 deletions
diff --git a/tests/agentzh.t b/tests/agentzh.t index 7591902..2e7c8ce 100644 --- a/tests/agentzh.t +++ b/tests/agentzh.t | |||
| @@ -66,8 +66,9 @@ print(cjson.encode({arr = empty_arr})) | |||
| 66 | === TEST 6: empty_array_mt and empty tables as objects (explicit) | 66 | === TEST 6: empty_array_mt and empty tables as objects (explicit) |
| 67 | --- lua | 67 | --- lua |
| 68 | local cjson = require "cjson" | 68 | local cjson = require "cjson" |
| 69 | local sort_json = require "tests.sort_json" | ||
| 69 | local empty_arr = setmetatable({}, cjson.empty_array_mt) | 70 | local empty_arr = setmetatable({}, cjson.empty_array_mt) |
| 70 | print(cjson.encode({obj = {}, arr = empty_arr})) | 71 | print(sort_json(cjson.encode({obj = {}, arr = empty_arr}))) |
| 71 | --- out | 72 | --- out |
| 72 | {"arr":[],"obj":{}} | 73 | {"arr":[],"obj":{}} |
| 73 | 74 | ||
| @@ -76,6 +77,7 @@ print(cjson.encode({obj = {}, arr = empty_arr})) | |||
| 76 | === TEST 7: empty_array_mt and empty tables as objects (explicit) | 77 | === TEST 7: empty_array_mt and empty tables as objects (explicit) |
| 77 | --- lua | 78 | --- lua |
| 78 | local cjson = require "cjson" | 79 | local cjson = require "cjson" |
| 80 | local sort_json = require "tests.sort_json" | ||
| 79 | cjson.encode_empty_table_as_object(true) | 81 | cjson.encode_empty_table_as_object(true) |
| 80 | local empty_arr = setmetatable({}, cjson.empty_array_mt) | 82 | local empty_arr = setmetatable({}, cjson.empty_array_mt) |
| 81 | local data = { | 83 | local data = { |
| @@ -88,15 +90,16 @@ local data = { | |||
| 88 | } | 90 | } |
| 89 | } | 91 | } |
| 90 | } | 92 | } |
| 91 | print(cjson.encode(data)) | 93 | print(sort_json(cjson.encode(data))) |
| 92 | --- out | 94 | --- out |
| 93 | {"foo":{"foobar":{"obj":{},"arr":[]},"obj":{}},"arr":[]} | 95 | {"arr":[],"foo":{"foobar":{"arr":[],"obj":{}},"obj":{}}} |
| 94 | 96 | ||
| 95 | 97 | ||
| 96 | 98 | ||
| 97 | === TEST 8: empty_array_mt on non-empty tables | 99 | === TEST 8: empty_array_mt on non-empty tables |
| 98 | --- lua | 100 | --- lua |
| 99 | local cjson = require "cjson" | 101 | local cjson = require "cjson" |
| 102 | local sort_json = require "tests.sort_json" | ||
| 100 | cjson.encode_empty_table_as_object(true) | 103 | cjson.encode_empty_table_as_object(true) |
| 101 | local array = {"hello", "world", "lua"} | 104 | local array = {"hello", "world", "lua"} |
| 102 | setmetatable(array, cjson.empty_array_mt) | 105 | setmetatable(array, cjson.empty_array_mt) |
| @@ -110,9 +113,9 @@ local data = { | |||
| 110 | } | 113 | } |
| 111 | } | 114 | } |
| 112 | } | 115 | } |
| 113 | print(cjson.encode(data)) | 116 | print(sort_json(cjson.encode(data))) |
| 114 | --- out | 117 | --- out |
| 115 | {"foo":{"foobar":{"obj":{},"arr":[]},"obj":{}},"arr":["hello","world","lua"]} | 118 | {"arr":["hello","world","lua"],"foo":{"foobar":{"arr":[],"obj":{}},"obj":{}}} |
| 116 | 119 | ||
| 117 | 120 | ||
| 118 | 121 | ||
diff --git a/tests/sort_json.lua b/tests/sort_json.lua new file mode 100644 index 0000000..c95ab3c --- /dev/null +++ b/tests/sort_json.lua | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | -- NOTE: This will only work for simple tests. It doesn't parse strings so if | ||
| 2 | -- you put any symbols like {?[], inside of a string literal then it will break | ||
| 3 | -- The point of this function is to test basic structures, and not test JSON | ||
| 4 | -- strings | ||
| 5 | |||
| 6 | local function sort_callback(str) | ||
| 7 | local inside = str:sub(2, -2) | ||
| 8 | |||
| 9 | local parts = {} | ||
| 10 | local buffer = "" | ||
| 11 | local pos = 1 | ||
| 12 | |||
| 13 | while true do | ||
| 14 | if pos > #inside then | ||
| 15 | break | ||
| 16 | end | ||
| 17 | |||
| 18 | local append | ||
| 19 | |||
| 20 | local parens = inside:match("^%b{}", pos) | ||
| 21 | if parens then | ||
| 22 | pos = pos + #parens | ||
| 23 | append = sort_callback(parens) | ||
| 24 | else | ||
| 25 | local array = inside:match("^%b[]", pos) | ||
| 26 | if array then | ||
| 27 | pos = pos + #array | ||
| 28 | append = array | ||
| 29 | else | ||
| 30 | local front = inside:sub(pos, pos) | ||
| 31 | pos = pos + 1 | ||
| 32 | |||
| 33 | if front == "," then | ||
| 34 | table.insert(parts, buffer) | ||
| 35 | buffer = "" | ||
| 36 | else | ||
| 37 | append = front | ||
| 38 | end | ||
| 39 | end | ||
| 40 | end | ||
| 41 | |||
| 42 | if append then | ||
| 43 | buffer = buffer .. append | ||
| 44 | end | ||
| 45 | end | ||
| 46 | |||
| 47 | if buffer ~= "" then | ||
| 48 | table.insert(parts, buffer) | ||
| 49 | end | ||
| 50 | |||
| 51 | table.sort(parts) | ||
| 52 | |||
| 53 | return "{" .. table.concat(parts, ",") .. "}" | ||
| 54 | end | ||
| 55 | |||
| 56 | local function sort_json(str) | ||
| 57 | return (str:gsub("%b{}", sort_callback)) | ||
| 58 | end | ||
| 59 | |||
| 60 | |||
| 61 | return sort_json | ||
