neatjson 0.9 → 0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE.txt +2 -2
- data/README.md +31 -22
- data/lib/neatjson.rb +35 -23
- data/neatjson.gemspec +1 -1
- data/test/test_neatjson.lua +83 -83
- data/test/tests.js +30 -1
- data/test/tests.lua +34 -2
- data/test/tests.rb +30 -0
- metadata +6 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d2820b11ac77b92de38f28231d4826cd1e77ad0f9140da5b9e41eaf995dee5ce
|
4
|
+
data.tar.gz: b5cdc8378b227f574f8de0d517e7964ca6cfe96e40ff30873d6a412cda5844f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1681f5edb27ec6075e5bfd1d9c8a9e806b3ee4d2f76dea65d97a45d5b22fa4feefa20b2507ff060dd424cca346b4bee6ebdcd05735543dde71170f4ad2d55125
|
7
|
+
data.tar.gz: 14a3138ab4eb40fce7f9052e250f7c1ca7394c460b3d3f4cc8ccd87d8b91bed870d395719c3c3a0343990284af37589ef5e3abc86bd0f58c2b40ed946197c8ba
|
data/LICENSE.txt
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
Copyright (c) 2015-
|
1
|
+
Copyright (c) 2015-2019 Gavin Kistner
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
4
|
|
5
5
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
6
|
|
7
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -189,29 +189,33 @@ var json = neatJSON( myValue, { arrayPadding:1, afterComma:1, beforeColonN:2, in
|
|
189
189
|
local json = neatJSON( myValue, { arrayPadding=1, afterComma=1, beforeColonN=2, indentLast=true } )
|
190
190
|
~~~
|
191
191
|
|
192
|
-
* `wrap`
|
193
|
-
* `indent`
|
194
|
-
* `indent_last`
|
195
|
-
* `short`
|
192
|
+
* `wrap` — Maximum line width before wrapping. Use `false` to never wrap, `true` to always wrap. default:`80`
|
193
|
+
* `indent` — Whitespace used to indent each level when wrapping. default:`" "` (two spaces)
|
194
|
+
* `indent_last` — Indent the closing bracket/brace for arrays and objects? default:`false`
|
195
|
+
* `short` — Put opening brackets on the same line as the first value, closing brackets on the same line as the last? default:`false`
|
196
196
|
* _This causes the `indent` and `indent_last` options to be ignored, instead basing indentation on array and object padding._
|
197
|
-
* `sort`
|
197
|
+
* `sort` — Sort objects' keys in alphabetical order (`true`), or supply a lambda for custom sorting. default:`false`
|
198
198
|
* If you supply a lambda to the `sort` option, it will be passed three values: the (string) name of the key, the associated value, and the object being sorted, e.g. `{ sort:->(key,value,hash){ Float(value) rescue Float::MAX } }`
|
199
|
-
* `aligned`
|
200
|
-
* `decimals`
|
201
|
-
* `
|
202
|
-
* `
|
203
|
-
* `
|
204
|
-
|
205
|
-
* `
|
206
|
-
* `
|
207
|
-
* `
|
208
|
-
* `
|
209
|
-
* `
|
210
|
-
* `
|
211
|
-
* `
|
212
|
-
* `
|
213
|
-
* `
|
214
|
-
* `
|
199
|
+
* `aligned` — When wrapping objects, line up the colons (per object)? default:`false`
|
200
|
+
* `decimals` — Decimal precision for non-integer numbers; use `false` to keep values precise. default:`false`
|
201
|
+
* `trim_trailing_zeros` — Remove extra zeros at the end of floats, e.g. `1.2000` becomes `1.2`. default:`false`
|
202
|
+
* `force_floats` — Force every integer value written to the file to be a float, e.g. `12` becomes `12.0`. default:`false`
|
203
|
+
* `force_floats_in` — Specify an array of object key names under which all integer values are treated as floats.
|
204
|
+
For example, serializing `{a:[1, 2, {a:3, b:4}], c:{a:5, d:6}` with `force_floats_in:['a']` would produce `{"a":[1.0, 2.0, {"a":3.0, "b":4}], "c":{"a":5.0, "d":6}}`.
|
205
|
+
* `array_padding` — Number of spaces to put inside brackets for arrays. default:`0`
|
206
|
+
* `object_padding` — Number of spaces to put inside braces for objects. default:`0`
|
207
|
+
* `padding` — Shorthand to set both `array_padding` and `object_padding`. default:`0`
|
208
|
+
* `before_comma` — Number of spaces to put before commas (for both arrays and objects). default:`0`
|
209
|
+
* `after_comma` — Number of spaces to put after commas (for both arrays and objects). default:`0`
|
210
|
+
* `around_comma` — Shorthand to set both `before_comma` and `after_comma`. default:`0`
|
211
|
+
* `before_colon_1` — Number of spaces before a colon when the object is on one line. default:`0`
|
212
|
+
* `after_colon_1` — Number of spaces after a colon when the object is on one line. default:`0`
|
213
|
+
* `before_colon_n` — Number of spaces before a colon when the object is on multiple lines. default:`0`
|
214
|
+
* `after_colon_n` — Number of spaces after a colon when the object is on multiple lines. default:`0`
|
215
|
+
* `before_colon` — Shorthand to set both `before_colon_1` and `before_colon_n`. default:`0`
|
216
|
+
* `after_colon` — Shorthand to set both `after_colon_1` and `after_colon_n`. default:`0`
|
217
|
+
* `around_colon` — Shorthand to set both `before_colon` and `after_colon`. default:`0`
|
218
|
+
* `lua` — (Lua only) Output a Lua table literal instead of JSON? default:`false`
|
215
219
|
* `emptyTablesAreObjects` — (Lua only) Should `{}` in Lua become a JSON object (`{}`) or JSON array (`[]`)? default:`false` (array)
|
216
220
|
|
217
221
|
You may omit the 'value' and/or 'object' parameters in your `sort` lambda if desired. For example:
|
@@ -257,7 +261,7 @@ _Note that the JavaScript and Lua versions of NeatJSON do not provide a mechanis
|
|
257
261
|
|
258
262
|
## License & Contact
|
259
263
|
|
260
|
-
NeatJSON is copyright ©2015–
|
264
|
+
NeatJSON is copyright ©2015–2022 by Gavin Kistner and is released under
|
261
265
|
the [MIT License](http://www.opensource.org/licenses/mit-license.php).
|
262
266
|
See the LICENSE.txt file for more details.
|
263
267
|
|
@@ -274,6 +278,11 @@ For other communication you can [email the author directly](mailto:!@phrogz.net?
|
|
274
278
|
|
275
279
|
## HISTORY
|
276
280
|
|
281
|
+
* **v0.10** — August 29, 2022
|
282
|
+
* Add `force_floats` and `force_floats_in` to support serialization for non-standard parsers that differentiate between integers and floats.
|
283
|
+
* Add `trim_trailing_zeros` option to convert the `decimals` output from e.g. `5.40000` to `5.4`.
|
284
|
+
* Convert JavaScript version to require ECMAScript 6 for performance.
|
285
|
+
|
277
286
|
* **v0.9** — July 29, 2019
|
278
287
|
* Add Lua version, serializing to both JSON and Lua table literals
|
279
288
|
* All languages serialize Infinity/-Infinity to JSON as `9e9999` and `-9e9999`
|
data/lib/neatjson.rb
CHANGED
@@ -6,13 +6,16 @@ module JSON
|
|
6
6
|
# @author Gavin Kistner <!@phrogz.net>
|
7
7
|
# @param object [Object] the object to serialize
|
8
8
|
# @param opts [Hash] the formatting options
|
9
|
-
# @option opts [Integer] :wrap
|
10
|
-
# @option opts [String] :indent
|
11
|
-
# @option opts [Boolean] :indent_last
|
12
|
-
# @option opts [Boolean] :short
|
13
|
-
# @option opts [Boolean] :sort
|
14
|
-
# @option opts [Boolean] :aligned
|
15
|
-
# @option opts [
|
9
|
+
# @option opts [Integer] :wrap (80) The maximum line width before wrapping. Use `false` to never wrap, or `true` to always wrap.
|
10
|
+
# @option opts [String] :indent (" ") Whitespace used to indent each level when wrapping (without the :short option).
|
11
|
+
# @option opts [Boolean] :indent_last (false) Indent the closing bracket for arrays and objects (without the :short option).
|
12
|
+
# @option opts [Boolean] :short (false) Keep the output 'short' when wrapping, putting opening brackets on the same line as the first value, and closing brackets on the same line as the last item.
|
13
|
+
# @option opts [Boolean] :sort (false) Sort the keys for objects to be in alphabetical order (`true`), or supply a lambda to determine ordering.
|
14
|
+
# @option opts [Boolean] :aligned (false) When wrapping objects, align the colons (only per object).
|
15
|
+
# @option opts [Boolean] :force_floats (false) Ensure that all integer values have `.0` after them.
|
16
|
+
# @option opts [Array] :force_floats_in ([]) Array of object key names to force floats inside of.
|
17
|
+
# @option opts [Integer] :decimals (null) Decimal precision to use for floats; omit to keep numeric values precise.
|
18
|
+
# @option opts [Boolean] :trim_trailing_zeros (false) Remove trailing zeros added by `decimals`` from the ends of floating point numbers.
|
16
19
|
# @option opts [Integer] :padding (0) Number of spaces to put inside brackets/braces for both arrays and objects.
|
17
20
|
# @option opts [Integer] :array_padding (0) Number of spaces to put inside brackets for arrays. Overrides `:padding`.
|
18
21
|
# @option opts [Integer] :object_padding (0) Number of spaces to put inside braces for objects. Overrides `:padding`.
|
@@ -37,6 +40,7 @@ module JSON
|
|
37
40
|
opts[:wrap] = 80 unless opts.key?(:wrap)
|
38
41
|
opts[:wrap] = -1 if opts[:wrap]==true
|
39
42
|
opts[:indent] ||= " "
|
43
|
+
opts[:force_floats_in]||= []
|
40
44
|
opts[:array_padding] ||= opts[:padding] || 0
|
41
45
|
opts[:object_padding] ||= opts[:padding] || 0
|
42
46
|
opts[:after_comma] ||= opts[:around_comma] || 0
|
@@ -56,21 +60,27 @@ module JSON
|
|
56
60
|
colonn= "#{' '*opts[:before_colon_n]}:#{' '*opts[:after_colon_n]}"
|
57
61
|
|
58
62
|
memoizer = {}
|
59
|
-
build = ->(o,indent) do
|
60
|
-
memoizer[[o,indent]] ||= case o
|
61
|
-
when String
|
63
|
+
build = ->(o,indent,floats_forced) do
|
64
|
+
memoizer[[o,indent,floats_forced]] ||= case o
|
65
|
+
when String then "#{indent}#{o.inspect}"
|
62
66
|
when Symbol then "#{indent}#{o.to_s.inspect}"
|
63
67
|
when TrueClass,FalseClass then "#{indent}#{o}"
|
64
68
|
when NilClass then "#{indent}null"
|
69
|
+
when Integer
|
70
|
+
floats_forced ? build[o.to_f, indent, floats_forced] : "#{indent}#{o.inspect}"
|
65
71
|
when Float
|
66
72
|
if o.infinite?
|
67
73
|
"#{indent}#{o<0 ? "-9e9999" : "9e9999"}"
|
68
74
|
elsif o.nan?
|
69
75
|
"#{indent}\"NaN\""
|
70
|
-
elsif (o==o.to_i) && (o.to_s !~ /e/)
|
71
|
-
build[o.to_i,indent]
|
76
|
+
elsif !floats_forced && (o==o.to_i) && (o.to_s !~ /e/)
|
77
|
+
build[o.to_i, indent, floats_forced]
|
72
78
|
elsif opts[:decimals]
|
73
|
-
|
79
|
+
if opts[:trim_trailing_zeros]
|
80
|
+
"#{indent}#{o.round(opts[:decimals])}"
|
81
|
+
else
|
82
|
+
"#{indent}%.#{opts[:decimals]}f" % o
|
83
|
+
end
|
74
84
|
else
|
75
85
|
"#{indent}#{o}"
|
76
86
|
end
|
@@ -79,19 +89,19 @@ module JSON
|
|
79
89
|
if o.empty?
|
80
90
|
"#{indent}[]"
|
81
91
|
else
|
82
|
-
pieces = o.map{ |v| build[v,''] }
|
92
|
+
pieces = o.map{ |v| build[v, '', floats_forced] }
|
83
93
|
one_line = "#{indent}[#{apad}#{pieces.join comma}#{apad}]"
|
84
94
|
if !opts[:wrap] || (one_line.length <= opts[:wrap])
|
85
95
|
one_line
|
86
96
|
elsif opts[:short]
|
87
97
|
indent2 = "#{indent} #{apad}"
|
88
|
-
pieces = o.map{ |v| build[
|
98
|
+
pieces = o.map{ |v| build[v, indent2, floats_forced] }
|
89
99
|
pieces[0] = pieces[0].sub indent2, "#{indent}[#{apad}"
|
90
100
|
pieces[pieces.length-1] = "#{pieces.last}#{apad}]"
|
91
101
|
pieces.join ",\n"
|
92
102
|
else
|
93
103
|
indent2 = "#{indent}#{opts[:indent]}"
|
94
|
-
"#{indent}[\n#{o.map{ |v| build[
|
104
|
+
"#{indent}[\n#{o.map{ |v| build[v, indent2, floats_forced] }.join ",\n"}\n#{opts[:indent_last] ? indent2 : indent}]"
|
95
105
|
end
|
96
106
|
end
|
97
107
|
|
@@ -108,7 +118,8 @@ module JSON
|
|
108
118
|
when 3 then o.sort_by{ |k,v| sort[k,v,o] }
|
109
119
|
end
|
110
120
|
end
|
111
|
-
|
121
|
+
keys = o.map{|x| x.first.to_s }
|
122
|
+
keyvals = o.map.with_index{ |(k,v),i| [ k.to_s.inspect, build[v, '', opts[:force_floats] || opts[:force_floats_in].include?(keys[i])] ] }
|
112
123
|
keyvals = keyvals.map{ |kv| kv.join(colon1) }.join(comma)
|
113
124
|
one_line = "#{indent}{#{opad}#{keyvals}#{opad}}"
|
114
125
|
if !opts[:wrap] || (one_line.length <= opts[:wrap])
|
@@ -122,11 +133,12 @@ module JSON
|
|
122
133
|
formatk = "%-#{longest}s"
|
123
134
|
keyvals.map!{ |k,v| [ formatk % k,v] }
|
124
135
|
end
|
125
|
-
keyvals.map
|
136
|
+
keyvals.map!.with_index do |(k,v),i|
|
137
|
+
floats_forced = opts[:force_floats] || opts[:force_floats_in].include?(keys[i])
|
126
138
|
indent2 = " "*"#{k}#{colonn}".length
|
127
|
-
one_line = "#{k}#{colonn}#{build[v,'']}"
|
139
|
+
one_line = "#{k}#{colonn}#{build[v, '', floats_forced]}"
|
128
140
|
if opts[:wrap] && (one_line.length > opts[:wrap]) && (v.is_a?(Array) || v.is_a?(Hash))
|
129
|
-
"#{k}#{colonn}#{build[v,indent2].lstrip}"
|
141
|
+
"#{k}#{colonn}#{build[v, indent2, floats_forced].lstrip}"
|
130
142
|
else
|
131
143
|
one_line
|
132
144
|
end
|
@@ -141,9 +153,9 @@ module JSON
|
|
141
153
|
end
|
142
154
|
indent2 = "#{indent}#{opts[:indent]}"
|
143
155
|
keyvals.map! do |k,v|
|
144
|
-
one_line = "#{k}#{colonn}#{build[v,'']}"
|
156
|
+
one_line = "#{k}#{colonn}#{build[v, '', floats_forced]}"
|
145
157
|
if opts[:wrap] && (one_line.length > opts[:wrap]) && (v.is_a?(Array) || v.is_a?(Hash))
|
146
|
-
"#{k}#{colonn}#{build[v,indent2].lstrip}"
|
158
|
+
"#{k}#{colonn}#{build[v, indent2, floats_forced].lstrip}"
|
147
159
|
else
|
148
160
|
one_line
|
149
161
|
end
|
@@ -158,6 +170,6 @@ module JSON
|
|
158
170
|
end
|
159
171
|
end
|
160
172
|
|
161
|
-
build[object,'']
|
173
|
+
build[object, '', opts[:force_floats]]
|
162
174
|
end
|
163
175
|
end
|
data/neatjson.gemspec
CHANGED
data/test/test_neatjson.lua
CHANGED
@@ -1,83 +1,83 @@
|
|
1
|
-
local function dump(v)
|
2
|
-
local reserved = {["and"]=1,["break"]=1,["do"]=1,["else"]=1,["elseif"]=1,["end"]=1,["false"]=1,["for"]=1,["function"]=1,["goto"]=1,["if"]=1,["in"]=1,["local"]=1,["nil"]=1,["not"]=1,["or"]=1,["repeat"]=1,["return"]=1,["then"]=1,["true"]=1,["until"]=1,["while"]=1}
|
3
|
-
local t=type(v)
|
4
|
-
if t=='table' then
|
5
|
-
local s,r={},{}
|
6
|
-
for i,v2 in ipairs(v) do s[i]=true table.insert(r,dump(v2)) end
|
7
|
-
for k,v2 in pairs(v) do
|
8
|
-
if not s[k] then
|
9
|
-
if type(k)=='string' and not reserved[k] and string.match(k,'^[%a_][%w_]*$') then
|
10
|
-
table.insert(r,k..'='..dump(v2))
|
11
|
-
else
|
12
|
-
table.insert(r,'['..dump(k)..']='..dump(v2))
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
return '{'..table.concat(r,', ')..'}'
|
17
|
-
elseif t=='string' then
|
18
|
-
return string.format('%q',v)
|
19
|
-
else
|
20
|
-
return tostring(v)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
package.path = '?.lua;../lua/?.lua'
|
26
|
-
local tests = require'tests'
|
27
|
-
local neatJSON = require'neatjson'
|
28
|
-
local startTime = os.clock()
|
29
|
-
local count,pass=0,0
|
30
|
-
for _,valtest in ipairs(tests) do
|
31
|
-
local value = valtest.value
|
32
|
-
for _,test in ipairs(valtest.tests) do
|
33
|
-
local cmd = "neatJSON("..dump(value)..(test.opts and (", "..dump(test.opts)) or '')..")"
|
34
|
-
local ok,err = pcall(function()
|
35
|
-
local json, success
|
36
|
-
if test.opts then
|
37
|
-
local opts = {}
|
38
|
-
for k,v in pairs(test.opts) do opts[k]=v end
|
39
|
-
json = neatJSON(value,opts)
|
40
|
-
else
|
41
|
-
json = neatJSON(value)
|
42
|
-
end
|
43
|
-
|
44
|
-
if type(test.json)=='string' then
|
45
|
-
success = json==test.json
|
46
|
-
else
|
47
|
-
-- If it's not a string, assume it's an array of acceptable string patterns
|
48
|
-
success = false
|
49
|
-
for _,testPattern in ipairs(test.json) do
|
50
|
-
if json:match(testPattern) then
|
51
|
-
success = true
|
52
|
-
break
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
if success then
|
58
|
-
pass = pass + 1
|
59
|
-
else
|
60
|
-
local expected = type(test.json)=='string' and test.json or table.concat(test.json, ' or ')
|
61
|
-
print(cmd)
|
62
|
-
print('EXPECTED')
|
63
|
-
print(expected)
|
64
|
-
print('ACTUAL')
|
65
|
-
print(json==nil and '(nil)' or #json==0 and '(empty string)' or json)
|
66
|
-
print('')
|
67
|
-
end
|
68
|
-
end)
|
69
|
-
if not ok then
|
70
|
-
print('Error running '..cmd)
|
71
|
-
print(err)
|
72
|
-
print('')
|
73
|
-
end
|
74
|
-
count = count + 1
|
75
|
-
end
|
76
|
-
end
|
77
|
-
local elapsed = os.clock()-startTime
|
78
|
-
print(("%d/%d test%s passed in %.2fms (%.0f tests per second)"):format(
|
79
|
-
pass, count,
|
80
|
-
count==1 and '' or 's',
|
81
|
-
elapsed,
|
82
|
-
1000 * count/elapsed
|
83
|
-
))
|
1
|
+
local function dump(v)
|
2
|
+
local reserved = {["and"]=1,["break"]=1,["do"]=1,["else"]=1,["elseif"]=1,["end"]=1,["false"]=1,["for"]=1,["function"]=1,["goto"]=1,["if"]=1,["in"]=1,["local"]=1,["nil"]=1,["not"]=1,["or"]=1,["repeat"]=1,["return"]=1,["then"]=1,["true"]=1,["until"]=1,["while"]=1}
|
3
|
+
local t=type(v)
|
4
|
+
if t=='table' then
|
5
|
+
local s,r={},{}
|
6
|
+
for i,v2 in ipairs(v) do s[i]=true table.insert(r,dump(v2)) end
|
7
|
+
for k,v2 in pairs(v) do
|
8
|
+
if not s[k] then
|
9
|
+
if type(k)=='string' and not reserved[k] and string.match(k,'^[%a_][%w_]*$') then
|
10
|
+
table.insert(r,k..'='..dump(v2))
|
11
|
+
else
|
12
|
+
table.insert(r,'['..dump(k)..']='..dump(v2))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
return '{'..table.concat(r,', ')..'}'
|
17
|
+
elseif t=='string' then
|
18
|
+
return string.format('%q',v)
|
19
|
+
else
|
20
|
+
return tostring(v)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
package.path = '?.lua;../lua/?.lua'
|
26
|
+
local tests = require'tests'
|
27
|
+
local neatJSON = require'neatjson'
|
28
|
+
local startTime = os.clock()
|
29
|
+
local count,pass=0,0
|
30
|
+
for _,valtest in ipairs(tests) do
|
31
|
+
local value = valtest.value
|
32
|
+
for _,test in ipairs(valtest.tests) do
|
33
|
+
local cmd = "neatJSON("..dump(value)..(test.opts and (", "..dump(test.opts)) or '')..")"
|
34
|
+
local ok,err = pcall(function()
|
35
|
+
local json, success
|
36
|
+
if test.opts then
|
37
|
+
local opts = {}
|
38
|
+
for k,v in pairs(test.opts) do opts[k]=v end
|
39
|
+
json = neatJSON(value,opts)
|
40
|
+
else
|
41
|
+
json = neatJSON(value)
|
42
|
+
end
|
43
|
+
|
44
|
+
if type(test.json)=='string' then
|
45
|
+
success = json==test.json
|
46
|
+
else
|
47
|
+
-- If it's not a string, assume it's an array of acceptable string patterns
|
48
|
+
success = false
|
49
|
+
for _,testPattern in ipairs(test.json) do
|
50
|
+
if json:match(testPattern) then
|
51
|
+
success = true
|
52
|
+
break
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if success then
|
58
|
+
pass = pass + 1
|
59
|
+
else
|
60
|
+
local expected = type(test.json)=='string' and test.json or table.concat(test.json, ' or ')
|
61
|
+
print(cmd)
|
62
|
+
print('EXPECTED')
|
63
|
+
print(expected)
|
64
|
+
print('ACTUAL')
|
65
|
+
print(json==nil and '(nil)' or #json==0 and '(empty string)' or json)
|
66
|
+
print('')
|
67
|
+
end
|
68
|
+
end)
|
69
|
+
if not ok then
|
70
|
+
print('Error running '..cmd)
|
71
|
+
print(err)
|
72
|
+
print('')
|
73
|
+
end
|
74
|
+
count = count + 1
|
75
|
+
end
|
76
|
+
end
|
77
|
+
local elapsed = os.clock()-startTime
|
78
|
+
print(("%d/%d test%s passed in %.2fms (%.0f tests per second)"):format(
|
79
|
+
pass, count,
|
80
|
+
count==1 and '' or 's',
|
81
|
+
elapsed,
|
82
|
+
1000 * count/elapsed
|
83
|
+
))
|
data/test/tests.js
CHANGED
@@ -15,6 +15,9 @@ exports.tests = [
|
|
15
15
|
{value:5.0001, tests:[
|
16
16
|
{json:"5.0001"},
|
17
17
|
{json:"5.000", opts:{decimals:3}},
|
18
|
+
{json:"5", opts:{decimals:3, trimTrailingZeros:true}},
|
19
|
+
{json:"5.0", opts:{decimals:3, trimTrailingZeros:true, forceFloats:true}},
|
20
|
+
{json:"5.000", opts:{decimals:3, trimTrailingZeros:false, forceFloats:true}},
|
18
21
|
]},
|
19
22
|
{value:4.2, tests:[
|
20
23
|
{json:"4.2"},
|
@@ -30,7 +33,6 @@ exports.tests = [
|
|
30
33
|
{value:-2.4, tests:[{json:"-2", opts:{decimals:0}}]},
|
31
34
|
|
32
35
|
{value:"foo", tests:[{json:"\"foo\""}]},
|
33
|
-
// {value: :foo, tests:[{json:"\"foo\""}]},
|
34
36
|
{value:"foo\nbar", tests:[{json:"\"foo\\nbar\""}]},
|
35
37
|
|
36
38
|
{value:[1,2,3,4,[5,6,7,[8,9,10],11,12]], tests:[
|
@@ -173,6 +175,33 @@ exports.tests = [
|
|
173
175
|
{ json:'{"inf":9e9999,"nan":"NaN","neginf":-9e9999}', opts:{sort:true} },
|
174
176
|
]},
|
175
177
|
|
178
|
+
{value:[0, 1, 1.1, 1.555555], tests:[
|
179
|
+
{ json:'[0,1,1.1,1.555555]', opts:{forceFloats:false} },
|
180
|
+
{ json:'[0.0,1.0,1.1,1.555555]', opts:{forceFloats:true} },
|
181
|
+
{ json:'[0.000,1.000,1.100,1.556]', opts:{forceFloats:true, decimals:3} },
|
182
|
+
{ json:'[0.0,1.0,1.1,1.556]', opts:{forceFloats:true, decimals:3, trimTrailingZeros:true} },
|
183
|
+
{ json:'[0,1,1.1,1.556]', opts:{forceFloats:false, decimals:3, trimTrailingZeros:true} },
|
184
|
+
]},
|
185
|
+
|
186
|
+
{value:{floats:[0, 1, 0.1, 1.555555], raw:[0, 1, 0.1, 1.555555]}, tests:[
|
187
|
+
{ json:'{"floats":[0,1,0.1,1.555555],"raw":[0,1,0.1,1.555555]}', opts:{forceFloats:false} },
|
188
|
+
{ json:'{"floats":[0.0,1.0,0.1,1.555555],"raw":[0.0,1.0,0.1,1.555555]}', opts:{forceFloats:true} },
|
189
|
+
{ json:'{"floats":[0.0,1.0,0.1,1.555555],"raw":[0,1,0.1,1.555555]}', opts:{forceFloatsIn:['floats']} },
|
190
|
+
|
191
|
+
{ json:'{"floats":[0,1,0.100,1.556],"raw":[0,1,0.100,1.556]}', opts:{forceFloats:false, decimals:3} },
|
192
|
+
{ json:'{"floats":[0.000,1.000,0.100,1.556],"raw":[0.000,1.000,0.100,1.556]}', opts:{forceFloats:true, decimals:3} },
|
193
|
+
{ json:'{"floats":[0.000,1.000,0.100,1.556],"raw":[0,1,0.100,1.556]}', opts:{forceFloatsIn:['floats'], decimals:3} },
|
194
|
+
|
195
|
+
{ json:'{"floats":[0,1,0.1,1.556],"raw":[0,1,0.1,1.556]}', opts:{forceFloats:false, decimals:3, trimTrailingZeros:true} },
|
196
|
+
{ json:'{"floats":[0.0,1.0,0.1,1.556],"raw":[0.0,1.0,0.1,1.556]}', opts:{forceFloats:true, decimals:3, trimTrailingZeros:true} },
|
197
|
+
{ json:'{"floats":[0.0,1.0,0.1,1.556],"raw":[0,1,0.1,1.556]}', opts:{forceFloatsIn:['floats'], decimals:3, trimTrailingZeros:true} },
|
198
|
+
]},
|
199
|
+
|
200
|
+
{value:[1,2,3,{a:[4,5,{a:6, b:7}], b:[8,9,{a:10, b:11}]}], tests:[
|
201
|
+
{ json:'[1,2,3,{"a":[4,5,{"a":6,"b":7}],"b":[8,9,{"a":10,"b":11}]}]', opts:{} },
|
202
|
+
{ json:'[1.0,2.0,3.0,{"a":[4.0,5.0,{"a":6.0,"b":7.0}],"b":[8.0,9.0,{"a":10.0,"b":11.0}]}]', opts:{forceFloats:true, wrap:false} },
|
203
|
+
{ json:'[1,2,3,{"a":[4.0,5.0,{"a":6.0,"b":7}],"b":[8,9,{"a":10.0,"b":11}]}]', opts:{forceFloatsIn:['a'], wrap:false} },
|
204
|
+
]},
|
176
205
|
|
177
206
|
// {value:Class.new{ def to_json(*a); {a:1}.to_json(*a); end }.new, tests:[
|
178
207
|
// { json:'{ "a":1}' },
|
data/test/tests.lua
CHANGED
@@ -14,6 +14,9 @@ return {
|
|
14
14
|
{value=5.0001, tests={
|
15
15
|
{json="5.0001"},
|
16
16
|
{json="5.000", opts={decimals=3}},
|
17
|
+
{json="5", opts={decimals=3, trimTrailingZeros=true}},
|
18
|
+
{json="5.0", opts={decimals=3, trimTrailingZeros=true, forceFloats=true}},
|
19
|
+
{json="5.000", opts={decimals=3, trimTrailingZeros=false, forceFloats=true}},
|
17
20
|
}},
|
18
21
|
{value=4.2, tests={
|
19
22
|
{json="4.2"},
|
@@ -174,11 +177,40 @@ return {
|
|
174
177
|
}},
|
175
178
|
|
176
179
|
{value={1,2,3,a=4,['for']=5}, tests={
|
177
|
-
{ json='{[1]=1,[2]=2,[3]=3,a=4,["for"]=5}', opts={lua=true, sort=true} }
|
180
|
+
{ json='{[1]=1,[2]=2,[3]=3,a=4,["for"]=5}', opts={lua=true, sort=true} },
|
181
|
+
{ json='{\n [1]=1,\n [2]=2,\n [3]=3,\n a=4,\n ["for"]=5\n}', opts={lua=true, sort=true, wrap=true} },
|
178
182
|
}},
|
179
183
|
|
180
184
|
{value={inf=1/0, neginf=-1/0, nan=0/0}, tests={
|
181
185
|
{ json='{"inf":9e9999,"nan":"NaN","neginf":-9e9999}', opts={sort=true} },
|
182
186
|
{ json='{inf=1/0,nan=0/0,neginf=-1/0}', opts={sort=true, lua=true} },
|
183
|
-
}}
|
187
|
+
}},
|
188
|
+
|
189
|
+
{value={0, 1, 1.1, 1.555555}, tests={
|
190
|
+
{ json='[0,1,1.1,1.555555]', opts={forceFloats=false} },
|
191
|
+
{ json='[0.0,1.0,1.1,1.555555]', opts={forceFloats=true} },
|
192
|
+
{ json='[0.000,1.000,1.100,1.556]', opts={forceFloats=true, decimals=3} },
|
193
|
+
{ json='[0.0,1.0,1.1,1.556]', opts={forceFloats=true, decimals=3, trimTrailingZeros=true} },
|
194
|
+
{ json='[0,1,1.1,1.556]', opts={forceFloats=false, decimals=3, trimTrailingZeros=true} },
|
195
|
+
}},
|
196
|
+
|
197
|
+
{value={floats={0, 1, 0.1, 1.555555}, raw={0, 1, 0.1, 1.555555}}, tests={
|
198
|
+
{ json='{"floats":[0,1,0.1,1.555555],"raw":[0,1,0.1,1.555555]}', opts={forceFloats=false, sort=true} },
|
199
|
+
{ json='{"floats":[0.0,1.0,0.1,1.555555],"raw":[0.0,1.0,0.1,1.555555]}', opts={forceFloats=true, sort=true} },
|
200
|
+
{ json='{"floats":[0.0,1.0,0.1,1.555555],"raw":[0,1,0.1,1.555555]}', opts={forceFloatsIn={'floats'}, sort=true} },
|
201
|
+
|
202
|
+
{ json='{"floats":[0,1,0.100,1.556],"raw":[0,1,0.100,1.556]}', opts={forceFloats=false, decimals=3, sort=true} },
|
203
|
+
{ json='{"floats":[0.000,1.000,0.100,1.556],"raw":[0.000,1.000,0.100,1.556]}', opts={forceFloats=true, decimals=3, sort=true} },
|
204
|
+
{ json='{"floats":[0.000,1.000,0.100,1.556],"raw":[0,1,0.100,1.556]}', opts={forceFloatsIn={'floats'}, decimals=3, sort=true} },
|
205
|
+
|
206
|
+
{ json='{"floats":[0,1,0.1,1.556],"raw":[0,1,0.1,1.556]}', opts={forceFloats=false, decimals=3, trimTrailingZeros=true, sort=true} },
|
207
|
+
{ json='{"floats":[0.0,1.0,0.1,1.556],"raw":[0.0,1.0,0.1,1.556]}', opts={forceFloats=true, decimals=3, trimTrailingZeros=true, sort=true} },
|
208
|
+
{ json='{"floats":[0.0,1.0,0.1,1.556],"raw":[0,1,0.1,1.556]}', opts={forceFloatsIn={'floats'}, decimals=3, trimTrailingZeros=true, sort=true} },
|
209
|
+
}},
|
210
|
+
|
211
|
+
-- {value={1,2,3,{a={4,5,{a=6, b=7}}, b={8,9,{a=10, b=11}}}}, tests={
|
212
|
+
-- { json='[1,2,3,{"a":[4,5,{"a":6,"b":7}],"b":[8,9,{"a":10,"b":11}]}]', opts={} },
|
213
|
+
-- { json='[1.0,2.0,3.0,{"a":[4.0,5.0,{"a":6.0,"b":7.0}],"b":[8.0,9.0,{"a":10.0,"b":11.0}]}]', opts={forceFloats=true, wrap=false} },
|
214
|
+
-- { json='[1,2,3,{"a":[4.0,5.0,{"a":6.0,"b":7}],"b":[8,9,{"a":10.0,"b":11}]}]', opts={forceFloatsIn={'a'}, wrap=false} },
|
215
|
+
-- }},
|
184
216
|
}
|
data/test/tests.rb
CHANGED
@@ -13,6 +13,8 @@ TESTS = [
|
|
13
13
|
{value:5.0001, tests:[
|
14
14
|
{json:"5.0001"},
|
15
15
|
{json:"5.000", opts:{decimals:3}},
|
16
|
+
{json:"5.0", opts:{decimals:3, trim_trailing_zeros:true, force_floats:true}},
|
17
|
+
{json:"5.000", opts:{decimals:3, trim_trailing_zeros:false, force_floats:true}},
|
16
18
|
]},
|
17
19
|
{value:4.2, tests:[
|
18
20
|
{json:"4.2"},
|
@@ -188,5 +190,33 @@ TESTS = [
|
|
188
190
|
{value:{inf:1.0/0, neginf:-1.0/0, nan:0.0/0}, tests:[
|
189
191
|
{ json:'{"inf":9e9999,"nan":"NaN","neginf":-9e9999}', opts:{sort:true} },
|
190
192
|
]},
|
193
|
+
|
194
|
+
{value:[0, 1, 1.1, 1.555555], tests:[
|
195
|
+
{ json:'[0,1,1.1,1.555555]', opts:{force_floats:false} },
|
196
|
+
{ json:'[0.0,1.0,1.1,1.555555]', opts:{force_floats:true} },
|
197
|
+
{ json:'[0.000,1.000,1.100,1.556]', opts:{force_floats:true, decimals:3} },
|
198
|
+
{ json:'[0.0,1.0,1.1,1.556]', opts:{force_floats:true, decimals:3, trim_trailing_zeros:true} },
|
199
|
+
{ json:'[0,1,1.1,1.556]', opts:{force_floats:false, decimals:3, trim_trailing_zeros:true} },
|
200
|
+
]},
|
201
|
+
|
202
|
+
{value:{floats:[0, 1, 0.1, 1.555555], raw:[0, 1, 0.1, 1.555555]}, tests:[
|
203
|
+
{ json:'{"floats":[0,1,0.1,1.555555],"raw":[0,1,0.1,1.555555]}', opts:{force_floats:false} },
|
204
|
+
{ json:'{"floats":[0.0,1.0,0.1,1.555555],"raw":[0.0,1.0,0.1,1.555555]}', opts:{force_floats:true} },
|
205
|
+
{ json:'{"floats":[0.0,1.0,0.1,1.555555],"raw":[0,1,0.1,1.555555]}', opts:{force_floats_in:['floats']} },
|
206
|
+
|
207
|
+
{ json:'{"floats":[0,1,0.100,1.556],"raw":[0,1,0.100,1.556]}', opts:{force_floats:false, decimals:3} },
|
208
|
+
{ json:'{"floats":[0.000,1.000,0.100,1.556],"raw":[0.000,1.000,0.100,1.556]}', opts:{force_floats:true, decimals:3} },
|
209
|
+
{ json:'{"floats":[0.000,1.000,0.100,1.556],"raw":[0,1,0.100,1.556]}', opts:{force_floats_in:['floats'], decimals:3} },
|
210
|
+
|
211
|
+
{ json:'{"floats":[0,1,0.1,1.556],"raw":[0,1,0.1,1.556]}', opts:{force_floats:false, decimals:3, trim_trailing_zeros:true} },
|
212
|
+
{ json:'{"floats":[0.0,1.0,0.1,1.556],"raw":[0.0,1.0,0.1,1.556]}', opts:{force_floats:true, decimals:3, trim_trailing_zeros:true} },
|
213
|
+
{ json:'{"floats":[0.0,1.0,0.1,1.556],"raw":[0,1,0.1,1.556]}', opts:{force_floats_in:['floats'], decimals:3, trim_trailing_zeros:true} },
|
214
|
+
]},
|
215
|
+
|
216
|
+
{value:[1,2,3,{a:[4,5,{a:6, b:7}], b:[8,9,{a:10, b:11}]}], tests:[
|
217
|
+
{ json:'[1,2,3,{"a":[4,5,{"a":6,"b":7}],"b":[8,9,{"a":10,"b":11}]}]', opts:{} },
|
218
|
+
{ json:'[1.0,2.0,3.0,{"a":[4.0,5.0,{"a":6.0,"b":7.0}],"b":[8.0,9.0,{"a":10.0,"b":11.0}]}]', opts:{force_floats:true, wrap:false} },
|
219
|
+
{ json:'[1,2,3,{"a":[4.0,5.0,{"a":6.0,"b":7}],"b":[8,9,{"a":10.0,"b":11}]}]', opts:{force_floats_in:['a'], wrap:false} },
|
220
|
+
]},
|
191
221
|
]
|
192
222
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neatjson
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.10'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gavin Kistner
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 'Generate JSON strings from Ruby objects with flexible formatting options.
|
14
14
|
Key features: keep arrays and objects on a single line when they fit; format floats
|
@@ -35,7 +35,7 @@ homepage: http://github.com/Phrogz/NeatJSON
|
|
35
35
|
licenses:
|
36
36
|
- MIT
|
37
37
|
metadata: {}
|
38
|
-
post_install_message:
|
38
|
+
post_install_message:
|
39
39
|
rdoc_options: []
|
40
40
|
require_paths:
|
41
41
|
- lib
|
@@ -50,9 +50,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
50
|
- !ruby/object:Gem::Version
|
51
51
|
version: '0'
|
52
52
|
requirements: []
|
53
|
-
|
54
|
-
|
55
|
-
signing_key:
|
53
|
+
rubygems_version: 3.2.3
|
54
|
+
signing_key:
|
56
55
|
specification_version: 4
|
57
56
|
summary: Pretty, powerful, flexible JSON generation.
|
58
57
|
test_files: []
|