neatjson 0.8.4 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1b3e65d59c946950e4f441db258d4c909547ff9f
4
- data.tar.gz: 25c864d3de32d04982061b81625a67765cc8113b
2
+ SHA256:
3
+ metadata.gz: 9896a4ef60379130606c3de3b7ce03ed65ce304ce7998470ecb74aaa95878f62
4
+ data.tar.gz: 7aa2196577ba6862be5bdf3811c6e2752157aa7b1520bae37697020a1d65d1cc
5
5
  SHA512:
6
- metadata.gz: 17b3d9b7e5d0145c324f9fa50dbfdda2f5e44fcb5c18ff5ab3ecb1308648672019f9d4fe9aadb771eb68ce33535cb2ef0b95978fbf9e8426f2735a9a711309ae
7
- data.tar.gz: ae0b881f1733c3e03afb6487cb92eeb1079d7a365e1b36d8a56a1593be3bdf4d3b2aa5e8b0037877d29e616161b52d8446dead59106a354356029d9e4e86a5f8
6
+ metadata.gz: 867bb6fa6cd5af52f708ded86d50adaf1b938e5f114c05cb9801ec40cf7ff0f08e1547400bf98f42087db2b0520eb682e85f88da9a3176f8ad61b611c8bd4944
7
+ data.tar.gz: b6b3d72a566b76b50baa82a7fde278f0b0a0c954e698c67fab36d835cf12cae7b1f9a56b5a0fd081ee94501735b6bbea439934057e91ca8f2607d1212ca70574
data/LICENSE.txt CHANGED
@@ -1,7 +1,7 @@
1
- Copyright (c) 2015-2018 Gavin Kistner
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
@@ -3,7 +3,7 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/neatjson.svg)](http://badge.fury.io/rb/neatjson)
4
4
  [![Gem Downloads](http://ruby-gem-downloads-badge.herokuapp.com/neatjson?type=total&color=brightgreen)](https://rubygems.org/gems/neatjson)
5
5
 
6
- Pretty-print your JSON in Ruby or JavaScript with more power than is provided by `JSON.pretty_generate` (Ruby) or `JSON.stringify` (JS). For example, like Ruby's `pp` (pretty print), NeatJSON can keep objects on one line if they fit, but break them over multiple lines if needed.
6
+ Pretty-print your JSON in Ruby or JavaScript or Lua with more power than is provided by `JSON.pretty_generate` (Ruby) or `JSON.stringify` (JS). For example, like Ruby's `pp` (pretty print), NeatJSON can keep objects on one line if they fit, but break them over multiple lines if needed.
7
7
 
8
8
  **Features (all optional):**
9
9
 
@@ -17,6 +17,8 @@ Pretty-print your JSON in Ruby or JavaScript with more power than is provided by
17
17
  * Adjust number of spaces before/after commas and colons (both for single- vs. multi-line).
18
18
  * Line up the values for an object across lines.
19
19
  * [Online webpage](http://phrogz.net/JS/NeatJSON) for conversions and experimenting with options.
20
+ * [Lua only] Produce Lua table serialization.
21
+
20
22
 
21
23
  ## Table of Contents
22
24
 
@@ -28,6 +30,7 @@ Pretty-print your JSON in Ruby or JavaScript with more power than is provided by
28
30
  * [TODO/Known Limitations](#todo-aka-known-limitations)
29
31
  * [History](#history)
30
32
 
33
+
31
34
  ## Installation
32
35
 
33
36
  * Ruby: `gem install neatjson`
@@ -44,6 +47,7 @@ require 'neatjson'
44
47
  json = JSON.neat_generate( value, options )
45
48
  ~~~
46
49
 
50
+
47
51
  **JavaScript (web)**:
48
52
 
49
53
  ~~~ html
@@ -61,9 +65,17 @@ const { neatJSON } = require('neatjson');
61
65
  var json = neatJSON( value, options );
62
66
  ~~~
63
67
 
68
+
69
+ **Lua**:
70
+
71
+ ~~~ lua
72
+ local neatJSON = require'neatjson'
73
+ local json = neatJSON(value, options)
74
+ ~~~
75
+
64
76
  ## Examples
65
77
 
66
- _The following are all in Ruby, but similar options apply in JavaScript._
78
+ _The following are all in Ruby, but similar options apply in JavaScript and Lua._
67
79
 
68
80
  ~~~ ruby
69
81
  require 'neatjson'
@@ -160,7 +172,7 @@ puts JSON.neat_generate( data, opts )
160
172
 
161
173
 
162
174
  ## Options
163
- You may pass any of the following options to `neat_generate` (Ruby) or `neatJSON` (JavaScript). **Note**: option names with underscores below use camelCase in JavaScript. For example:
175
+ You may pass any of the following options to `neat_generate` (Ruby) or `neatJSON` (JavaScript/Lua). **Note**: option names with underscores below use camelCase in JavaScript and Lua. For example:
164
176
 
165
177
  ~~~ ruby
166
178
  # Ruby
@@ -172,28 +184,39 @@ json = JSON.neat_generate my_value, array_padding:1, after_comma:1, before_colon
172
184
  var json = neatJSON( myValue, { arrayPadding:1, afterComma:1, beforeColonN:2, indentLast:true } );
173
185
  ~~~
174
186
 
175
- * `wrap` — Maximum line width before wrapping. Use `false` to never wrap, `true` to always wrap. default:`80`
176
- * `indent` — Whitespace used to indent each level when wrapping. default:`" "` (two spaces)
177
- * `indent_last` — Indent the closing bracket/brace for arrays and objects? default:`false`
178
- * `short` — Put opening brackets on the same line as the first value, closing brackets on the same line as the last? default:`false`
187
+ ~~~ lua
188
+ -- Lua
189
+ local json = neatJSON( myValue, { arrayPadding=1, afterComma=1, beforeColonN=2, indentLast=true } )
190
+ ~~~
191
+
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`
179
196
  * _This causes the `indent` and `indent_last` options to be ignored, instead basing indentation on array and object padding._
180
- * `sort` — Sort objects' keys in alphabetical order (`true`), or supply a lambda for custom sorting. default:`false`
197
+ * `sort` — Sort objects' keys in alphabetical order (`true`), or supply a lambda for custom sorting. default:`false`
181
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 } }`
182
- * `aligned` — When wrapping objects, line up the colons (per object)? default:`false`
183
- * `decimals` — Decimal precision for non-integer numbers; use `false` to keep values precise. default:`false`
184
- * `array_padding` Number of spaces to put inside brackets for arrays. default:`0`
185
- * `object_padding` Number of spaces to put inside braces for objects. default:`0`
186
- * `padding` Shorthand to set both `array_padding` and `object_padding`. default:`0`
187
- * `before_comma` — Number of spaces to put before commas (for both arrays and objects). default:`0`
188
- * `after_comma` — Number of spaces to put after commas (for both arrays and objects). default:`0`
189
- * `around_comma` Shorthand to set both `before_comma` and `after_comma`. default:`0`
190
- * `before_colon_1` Number of spaces before a colon when the object is on one line. default:`0`
191
- * `after_colon_1` — Number of spaces after a colon when the object is on one line. default:`0`
192
- * `before_colon_n` — Number of spaces before a colon when the object is on multiple lines. default:`0`
193
- * `after_colon_n` Number of spaces after a colon when the object is on multiple lines. default:`0`
194
- * `before_colon` Shorthand to set both `before_colon_1` and `before_colon_n`. default:`0`
195
- * `after_colon` Shorthand to set both `after_colon_1` and `after_colon_n`. default:`0`
196
- * `around_colon` Shorthand to set both `before_colon` and `after_colon`. default:`0`
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`
219
+ * `emptyTablesAreObjects` — (Lua only) Should `{}` in Lua become a JSON object (`{}`) or JSON array (`[]`)? default:`false` (array)
197
220
 
198
221
  You may omit the 'value' and/or 'object' parameters in your `sort` lambda if desired. For example:
199
222
 
@@ -233,12 +256,12 @@ neatJSON( obj, { sort:function(k,v){ return countByValue[v] } } ); // so
233
256
  // {"d":1,"a":2,"b":2,"e":3,"c":3,"f":3}
234
257
  ~~~
235
258
 
236
- _Note that the JavaScript version of NeatJSON does not provide a mechanism for cascading sort in the same manner as Ruby._
259
+ _Note that the JavaScript and Lua versions of NeatJSON do not provide a mechanism for cascading sort in the same manner as Ruby._
237
260
 
238
261
 
239
262
  ## License & Contact
240
263
 
241
- NeatJSON is copyright ©2015–2017 by Gavin Kistner and is released under
264
+ NeatJSON is copyright ©2015–2022 by Gavin Kistner and is released under
242
265
  the [MIT License](http://www.opensource.org/licenses/mit-license.php).
243
266
  See the LICENSE.txt file for more details.
244
267
 
@@ -250,12 +273,21 @@ For other communication you can [email the author directly](mailto:!@phrogz.net?
250
273
 
251
274
  * Figure out the best way to play with custom objects that use `to_json` for their representation.
252
275
  * Detect circular references.
253
- * Possibly allow illegal JSON values like `NaN` or `Infinity`.
254
276
  * Possibly allow "JSON5" output (legal identifiers unquoted, etc.)
255
277
 
256
278
 
257
279
  ## HISTORY
258
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
+
286
+ * **v0.9** — July 29, 2019
287
+ * Add Lua version, serializing to both JSON and Lua table literals
288
+ * All languages serialize Infinity/-Infinity to JSON as `9e9999` and `-9e9999`
289
+ * All languages serialize NaN to JSON as `"NaN"`
290
+
259
291
  * **v0.8.4** — May 3, 2018
260
292
  * Fix issue #27: Default sorting fails with on objects with mixed keys [Ruby only]
261
293
  * _Thanks Reid Beels_
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 (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 [Integer] :decimals (null) Decimal precision to use for floats; omit to keep numberic values precise.
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,17 +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,Integer then "#{indent}#{o.inspect}"
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
- if (o==o.to_i) && (o.to_s !~ /e/)
67
- build[o.to_i,indent]
72
+ if o.infinite?
73
+ "#{indent}#{o<0 ? "-9e9999" : "9e9999"}"
74
+ elsif o.nan?
75
+ "#{indent}\"NaN\""
76
+ elsif !floats_forced && (o==o.to_i) && (o.to_s !~ /e/)
77
+ build[o.to_i, indent, floats_forced]
68
78
  elsif opts[:decimals]
69
- "#{indent}%.#{opts[:decimals]}f" % o
79
+ if opts[:trim_trailing_zeros]
80
+ "#{indent}#{o.round(opts[:decimals])}"
81
+ else
82
+ "#{indent}%.#{opts[:decimals]}f" % o
83
+ end
70
84
  else
71
85
  "#{indent}#{o}"
72
86
  end
@@ -75,19 +89,19 @@ module JSON
75
89
  if o.empty?
76
90
  "#{indent}[]"
77
91
  else
78
- pieces = o.map{ |v| build[v,''] }
92
+ pieces = o.map{ |v| build[v, '', floats_forced] }
79
93
  one_line = "#{indent}[#{apad}#{pieces.join comma}#{apad}]"
80
94
  if !opts[:wrap] || (one_line.length <= opts[:wrap])
81
95
  one_line
82
96
  elsif opts[:short]
83
97
  indent2 = "#{indent} #{apad}"
84
- pieces = o.map{ |v| build[ v,indent2 ] }
98
+ pieces = o.map{ |v| build[v, indent2, floats_forced] }
85
99
  pieces[0] = pieces[0].sub indent2, "#{indent}[#{apad}"
86
100
  pieces[pieces.length-1] = "#{pieces.last}#{apad}]"
87
101
  pieces.join ",\n"
88
102
  else
89
103
  indent2 = "#{indent}#{opts[:indent]}"
90
- "#{indent}[\n#{o.map{ |v| build[ v, indent2 ] }.join ",\n"}\n#{opts[:indent_last] ? indent2 : indent}]"
104
+ "#{indent}[\n#{o.map{ |v| build[v, indent2, floats_forced] }.join ",\n"}\n#{opts[:indent_last] ? indent2 : indent}]"
91
105
  end
92
106
  end
93
107
 
@@ -104,7 +118,8 @@ module JSON
104
118
  when 3 then o.sort_by{ |k,v| sort[k,v,o] }
105
119
  end
106
120
  end
107
- keyvals = o.map{ |k,v| [ k.to_s.inspect, build[v,''] ] }
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])] ] }
108
123
  keyvals = keyvals.map{ |kv| kv.join(colon1) }.join(comma)
109
124
  one_line = "#{indent}{#{opad}#{keyvals}#{opad}}"
110
125
  if !opts[:wrap] || (one_line.length <= opts[:wrap])
@@ -118,11 +133,12 @@ module JSON
118
133
  formatk = "%-#{longest}s"
119
134
  keyvals.map!{ |k,v| [ formatk % k,v] }
120
135
  end
121
- keyvals.map! do |k,v|
136
+ keyvals.map!.with_index do |(k,v),i|
137
+ floats_forced = opts[:force_floats] || opts[:force_floats_in].include?(keys[i])
122
138
  indent2 = " "*"#{k}#{colonn}".length
123
- one_line = "#{k}#{colonn}#{build[v,'']}"
139
+ one_line = "#{k}#{colonn}#{build[v, '', floats_forced]}"
124
140
  if opts[:wrap] && (one_line.length > opts[:wrap]) && (v.is_a?(Array) || v.is_a?(Hash))
125
- "#{k}#{colonn}#{build[v,indent2].lstrip}"
141
+ "#{k}#{colonn}#{build[v, indent2, floats_forced].lstrip}"
126
142
  else
127
143
  one_line
128
144
  end
@@ -136,10 +152,11 @@ module JSON
136
152
  keyvals.map!{ |k,v| [ formatk % k,v] }
137
153
  end
138
154
  indent2 = "#{indent}#{opts[:indent]}"
139
- keyvals.map! do |k,v|
140
- one_line = "#{k}#{colonn}#{build[v,'']}"
155
+ keyvals.map!.with_index do |(k,v),i|
156
+ floats_forced = opts[:force_floats] || opts[:force_floats_in].include?(keys[i])
157
+ one_line = "#{k}#{colonn}#{build[v, '', floats_forced]}"
141
158
  if opts[:wrap] && (one_line.length > opts[:wrap]) && (v.is_a?(Array) || v.is_a?(Hash))
142
- "#{k}#{colonn}#{build[v,indent2].lstrip}"
159
+ "#{k}#{colonn}#{build[v, indent2, floats_forced].lstrip}"
143
160
  else
144
161
  one_line
145
162
  end
@@ -154,6 +171,6 @@ module JSON
154
171
  end
155
172
  end
156
173
 
157
- build[object,'']
174
+ build[object, '', opts[:force_floats]]
158
175
  end
159
176
  end
data/neatjson.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
  require 'date'
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "neatjson"
5
- s.version = "0.8.4"
5
+ s.version = "0.10.1"
6
6
  s.date = Date.today.iso8601
7
7
  s.authors = ["Gavin Kistner"]
8
8
  s.email = "gavin@phrogz.net"
@@ -0,0 +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
+ ))
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:[
@@ -169,6 +171,46 @@ exports.tests = [
169
171
  { json:"{\n \"a\":{\n \"b\":{\n \"c\":{\n \"d\":{\n \"e\":{\n \"f\":{\n \"g\":{\n \"h\":{\n \"i\":{\n \"j\":{\n \"k\":{\n \"l\":{\n \"m\":1\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}", opts:{wrap:1} },
170
172
  ]},
171
173
 
174
+ {value:{inf:1/0, neginf:-1/0, nan:0/0}, tests:[
175
+ { json:'{"inf":9e9999,"nan":"NaN","neginf":-9e9999}', opts:{sort:true} },
176
+ ]},
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
+ ]},
205
+
206
+ {value:[1,2,3, {bar:[4,5,6], foo:[7,8,9]}], tests:[
207
+ { json:'[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4,5,6],\n\t\t"foo":[7,8,9]\n\t}\n]', opts:{wrap:20, indent:"\t"} },
208
+ { json:'[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4.0,5.0,6.0],\n\t\t"foo":[7,8,9]\n\t}\n]', opts:{wrap:20, indent:"\t", forceFloatsIn:['bar']} },
209
+ { json:'[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4,5,6],\n\t\t"foo":[7.0,8.0,9.0]\n\t}\n]', opts:{wrap:20, indent:"\t", forceFloatsIn:['foo']} },
210
+ { json:'[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4.0,5.0,6.0],\n\t\t"foo":[7.0,8.0,9.0]\n\t}\n]', opts:{wrap:20, indent:"\t", forceFloatsIn:['foo', 'bar']} },
211
+ { json:'[\n\t1.0,\n\t2.0,\n\t3.0,\n\t{\n\t\t"bar":[4.0,5.0,6.0],\n\t\t"foo":[7.0,8.0,9.0]\n\t}\n]', opts:{wrap:20, indent:"\t", forceFloats:true} },
212
+ ]},
213
+
172
214
  // {value:Class.new{ def to_json(*a); {a:1}.to_json(*a); end }.new, tests:[
173
215
  // { json:'{ "a":1}' },
174
216
  // { json:'{ "a":1}', opts:{wrap:true} },
data/test/tests.lua ADDED
@@ -0,0 +1,225 @@
1
+ return {
2
+ {value=true, tests={{json="true" }}},
3
+ {value=false, tests={{json="false" }}},
4
+ {value=nil, tests={{json="null" }}},
5
+ {value=5, tests={
6
+ {json="5"},
7
+ {json="5", opts={decimals=3}},
8
+ }},
9
+ {value=5.0, tests={
10
+ {json="5"},
11
+ {json="5", opts={lua=true}},
12
+ {json="5", opts={decimals=3}},
13
+ }},
14
+ {value=5.0001, tests={
15
+ {json="5.0001"},
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}},
20
+ }},
21
+ {value=4.2, tests={
22
+ {json="4.2"},
23
+ {json="4", opts={decimals=0}},
24
+ {json="4.20",opts={decimals=2}},
25
+ }},
26
+ {value=4.199, tests={{json="4.20", opts={decimals=2}}}},
27
+ {value=4.204, tests={{json="4.20", opts={decimals=2}}}},
28
+ {value=-1.9, tests={{json="-2", opts={decimals=0}}}},
29
+ {value=-2.4, tests={{json="-2", opts={decimals=0}}}},
30
+ {value=1e23, tests={{json={'^1%.0+e%+0*23$', '^1e%+0*23$'}}}},
31
+ {value=1e-9, tests={{json={'^1%.0+e%-0*9$', '^1e%-0*9$'}}}},
32
+ {value=-2.4, tests={{json="-2", opts={decimals=0}}}},
33
+
34
+ {value="foo", tests={{json="\"foo\""}}},
35
+ -- {value= :foo, tests={{json="\"foo\""}}},
36
+ {value="foo\nbar", tests={{json="\"foo\\nbar\""}}},
37
+
38
+ {value={1,2,3,4,{5,6,7,{8,9,10},11,12}}, tests={
39
+ { json="[1,2,3,4,[5,6,7,[8,9,10],11,12]]" },
40
+ { json="{1,2,3,4,{5,6,7,{8,9,10},11,12}}", opts={lua=true} },
41
+ { json="[\n 1,\n 2,\n 3,\n 4,\n [5,6,7,[8,9,10],11,12]\n]", opts={wrap=30} },
42
+ { json="[\n 1,\n 2,\n 3,\n 4,\n [\n 5,\n 6,\n 7,\n [8,9,10],\n 11,\n 12\n ]\n]", opts={wrap=20} },
43
+ { json="[\n 1,\n 2,\n 3,\n 4,\n [\n 5,\n 6,\n 7,\n [\n 8,\n 9,\n 10\n ],\n 11,\n 12\n ]\n]", opts={wrap=true} },
44
+ { json="[\n\t1,\n\t2,\n\t3,\n\t4,\n\t[\n\t\t5,\n\t\t6,\n\t\t7,\n\t\t[\n\t\t\t8,\n\t\t\t9,\n\t\t\t10\n\t\t],\n\t\t11,\n\t\t12\n\t]\n]", opts={wrap=true,indent="\t"} },
45
+ { json="[1,2,3,4,[5,6,7,[8,9,10],11,12]]", opts={arrayPadding=0} },
46
+ { json="[ 1,2,3,4,[ 5,6,7,[ 8,9,10 ],11,12 ] ]", opts={arrayPadding=1} },
47
+ { json="[ 1,2,3,4,[ 5,6,7,[ 8,9,10 ],11,12 ] ]", opts={arrayPadding=2} },
48
+ { json="[1, 2, 3, 4, [5, 6, 7, [8, 9, 10], 11, 12]]", opts={afterComma=1} },
49
+ { json="[ 1, 2, 3, 4, [ 5, 6, 7, [ 8, 9, 10 ], 11, 12 ] ]", opts={afterComma=1,arrayPadding=1} },
50
+ { json="[1,\n 2,\n 3,\n 4,\n [5,\n 6,\n 7,\n [8,\n 9,\n 10],\n 11,\n 12]]", opts={short=true,wrap=true} },
51
+ { json="[1,\n 2,\n 3,\n 4,\n [5,\n 6,\n 7,\n [8,\n 9,\n 10],\n 11,\n 12]]", opts={short=true,wrap=true,afterComma=1} },
52
+ { json="[ 1,\n 2,\n 3,\n 4,\n [ 5,\n 6,\n 7,\n [ 8,\n 9,\n 10 ],\n 11,\n 12 ] ]", opts={short=true,wrap=true,arrayPadding=1} },
53
+ }},
54
+
55
+ {value={1,2,3}, tests={
56
+ { json="[1,2,3]" },
57
+ { json="[1 ,2 ,3]", opts={beforeComma=1} },
58
+ { json="[1 , 2 , 3]", opts={aroundComma=1} },
59
+ { json="[\n\t1,\n\t2,\n\t3\n]", opts={wrap=true,indent="\t"} },
60
+ { json="[\n\t1,\n\t2,\n\t3\n\t]", opts={wrap=true,indent="\t",indentLast=true} },
61
+ }},
62
+
63
+ {value={b=1,a=2}, tests={
64
+ { json={'{"b":1,"a":2}','{"a":2,"b":1}'} },
65
+ { json={'{b=1,a=2}','{a=2,b=1}'}, opts={lua=true} },
66
+ { json='{"a":2,"b":1}', opts={sorted=true} },
67
+ { json='{"a":2,"b":1}', opts={sort=true} },
68
+ { json='{"a":2, "b":1}', opts={sorted=true,afterComma=1} },
69
+ { json='{"a" :2,"b" :1}', opts={sorted=true,beforeColon=1} },
70
+ { json='{"a": 2,"b": 1}', opts={sorted=true,afterColon=1} },
71
+ { json='{"a" : 2,"b" : 1}', opts={sorted=true,beforeColon=1,afterColon=1} },
72
+ { json='{"a" : 2, "b" : 1}', opts={sorted=true,beforeColon=1,afterColon=1,afterComma=1} },
73
+ { json='{ "a" : 2, "b" : 1 }', opts={sorted=true,beforeColon=1,afterColon=1,afterComma=1,padding=1} },
74
+ { json='{ "a" : 2, "b" : 1 }', opts={sorted=true,aroundColon=1,afterComma=1,objectPadding=1} },
75
+ { json='{"a" : 2, "b" : 1}', opts={sorted=true,beforeColon=1,afterColon=1,afterComma=1,arrayPadding=1} },
76
+ { json='{ "a" : 2, "b" : 1 }', opts={sorted=true,aroundColon=2,afterComma=1,padding=2} },
77
+ { json='{ "a":2, "b":1 }', opts={sorted=true,afterComma=1,padding=2} },
78
+ { json={'{"b": 1,"a": 2}','{"a": 2,"b": 1}'}, opts={afterColon1=2} },
79
+ { json={'{"b" : 1,"a" : 2}','{"a" : 2,"b" : 1}'}, opts={aroundColon1=2} },
80
+ { json={"{\n \"b\":1,\n \"a\":2\n}","{\n \"a\":2,\n \"b\":1\n}"}, opts={wrap=true,aroundColon1=2} },
81
+ { json={"{\n \"b\": 1,\n \"a\": 2\n}","{\n \"a\": 2,\n \"b\": 1\n}"}, opts={wrap=true,afterColon=1} },
82
+ { json={"{\n \"b\": 1,\n \"a\": 2\n}","{\n \"a\": 2,\n \"b\": 1\n}"}, opts={wrap=true,afterColonN=1} },
83
+ { json="{\"a\":2,\n \"b\":1}", opts={sort=true,wrap=true,short=true} },
84
+ { json="{\"a\": 2,\n \"b\": 1}", opts={sort=true,wrap=true,short=true,afterColon=1} },
85
+ { json="{\"a\": 2,\n \"b\": 1}", opts={sort=true,wrap=true,short=true,afterColonN=1} },
86
+ { json="{\"a\":2,\n \"b\":1}", opts={sort=true,wrap=true,short=true,afterColon1=1} },
87
+ }},
88
+
89
+ {value={b=1,aaa=2,cc=3}, tests={
90
+ { json="{\n \"aaa\":2,\n \"b\":1,\n \"cc\":3\n}", opts={sort=true,wrap=true} },
91
+ { json="{\n \"aaa\":2,\n \"b\" :1,\n \"cc\" :3\n}", opts={sort=true,wrap=true,aligned=true} },
92
+ { json='{"aaa":2,"b":1,"cc":3}', opts={sort=true,aligned=true} },
93
+ { json="{\n \"aaa\":2,\n \"b\" :1,\n \"cc\" :3\n}", opts={wrap=true,aligned=true,sorted=true} },
94
+ }},
95
+
96
+ {value={a=1}, tests={
97
+ { json='{"a":1}' },
98
+ { json="{\n \"a\":1\n}", opts={wrap=true} },
99
+ { json="{\n \"a\":1\n }", opts={wrap=true, indentLast=true} },
100
+ { json="{\n \"a\":1\n }", opts={wrap=true, indentLast=true, indent=" " } },
101
+ }},
102
+
103
+ {value={b=17, a=42}, tests={
104
+ { json="{\"a\":42,\n \"b\":17}", opts={wrap=10,sorted=true,short=true} },
105
+ { json="{\"a\":42,\n \"b\":17}", opts={wrap=10,sort=true, short=true} },
106
+ { json="{\n \"a\":42,\n \"b\":17\n}", opts={wrap=1,sorted=true} },
107
+ { json="{\n \"a\":42,\n \"b\":17\n}", opts={wrap=1,sort=true} },
108
+ { json="{\"a\":42,\"b\":17}", opts={wrap=false, sort=function(k) return k end } },
109
+ { json="{\"b\":17,\"a\":42}", opts={wrap=false, sort=function(k,v) return v end } },
110
+ { json="{\"a\":42,\"b\":17}", opts={wrap=false, sort=function(k,v) return -v end } },
111
+ { json="{\"a\":42,\"b\":17}", opts={wrap=false, sort=function(k,v,o) return v==o.a and 0 or 1 end } },
112
+ { json="{\n\"b\":17,\n\"a\":42\n}", opts={wrap=1,indent="",sort=function(k) return k=="a" and 1 or 0 end } },
113
+ { json="{\n\"a\":42,\n\"b\":17\n}", opts={wrap=1,indent="",sort=function(k) return k=="a" and 0 or 1 end } },
114
+ }},
115
+
116
+ {value={1,{a=2},3}, tests={
117
+ { json='[1,{"a":2},3]' },
118
+ { json='[ 1,{ "a":2 },3 ]', opts={padding=1} },
119
+ { json='[ 1, { "a":2 }, 3 ]', opts={padding=1,afterComma=1} },
120
+ { json="[\n 1,\n {\n \"a\":2\n },\n 3\n]", opts={wrap=true} },
121
+ { json="[\n 1,\n {\"a\":2},\n 3\n]", opts={wrap=10} },
122
+ { json="[\n 1,\n {\n \"a\":2\n },\n 3\n ]", opts={wrap=true,indentLast=true} },
123
+ }},
124
+
125
+ {value={1,{a=2,b=3},4}, tests={
126
+ { json={"[1,\n {\"a\":2,\n \"b\":3},\n 4]","[1,\n {\"b\":3,\n \"a\":2},\n 4]"}, opts={wrap=0,short=true} },
127
+ }},
128
+
129
+ {value={a=1,b={2,3,4},c=3}, tests={
130
+ { json='{"a":1,"b":[2,3,4],"c":3}', opts={sort=true} },
131
+ { json="{\n \"a\":1,\n \"b\":[2,3,4],\n \"c\":3\n}", opts={sort=true,wrap=10} },
132
+ { json="{\n \"a\":1,\n \"b\":[\n 2,\n 3,\n 4\n ],\n \"c\":3\n}", opts={sort=true,wrap=true} },
133
+ { json="{\n \"a\":1,\n \"b\":[\n 2,\n 3,\n 4\n ],\n \"c\":3\n }", opts={sort=true,wrap=true,indentLast=true} },
134
+ }},
135
+
136
+ {value={hooo=42,whee={'yaaa','oooo','booy'},zoop="whoop"}, tests={
137
+ { json="{\"hooo\":42,\n \"whee\":[\"yaaa\",\n \"oooo\",\n \"booy\"],\n \"zoop\":\"whoop\"}", opts={sort=true,wrap=20,short=true} },
138
+ }},
139
+
140
+ {value={ a={ {x="foo",y="jim"}, {x="bar",y="jam"} } }, tests={
141
+ { json="{\"a\":[{\"x\":\"foo\",\n \"y\":\"jim\"},\n {\"x\":\"bar\",\n \"y\":\"jam\"}]}", opts={sort=true,wrap=true,short=true} },
142
+ }},
143
+
144
+ {value={abcdefghij={{abcdefghijklmnop={}}}}, tests={
145
+ { json='{"abcdefghij":[{"abcdefghijklmnop":[]}]}' },
146
+ { json='{"abcdefghij":[{"abcdefghijklmnop":{}}]}', opts={emptyTablesAreObjects=true} },
147
+ { json='{"abcdefghij" : [{"abcdefghijklmnop" : []}]}', opts={wrap=1, short=true, aroundColonN=1} },
148
+ }},
149
+
150
+ {value={foo={}}, tests={
151
+ { json='{"foo":[]}' },
152
+ { json='{"foo":[]}', opts={wrap=false} },
153
+ { json='{\n "foo":[]\n}', opts={wrap=5} },
154
+ { json='{"foo":[]}', opts={wrap=1, short=true} },
155
+ }},
156
+
157
+ {value={"foo",{},"bar"}, tests={
158
+ { json='[\n "foo",\n {},\n "bar"\n]', opts={wrap=1, emptyTablesAreObjects=true} },
159
+ { json='[\n "foo",\n [],\n "bar"\n]', opts={wrap=1} },
160
+ { json='["foo",\n {},\n "bar"]', opts={wrap=1, short=true, emptyTablesAreObjects=true} },
161
+ { json='["foo",\n [],\n "bar"]', opts={wrap=1, short=true} },
162
+ }},
163
+
164
+ {value={"foo",{},"bar"}, tests={
165
+ { json='[\n "foo",\n [],\n "bar"\n]', opts={wrap=1} },
166
+ { json='["foo",\n [],\n "bar"]', opts={wrap=1, short=true} },
167
+ }},
168
+
169
+ {value={"foo",{{},{{foo={}},42}},"bar"}, tests={
170
+ { json='["foo",\n [[],\n [{"foo":[]},\n 42]],\n "bar"]', opts={wrap=1, short=true} },
171
+ }},
172
+
173
+ {value={a={b={c={d={e={f={g={h={i={j={k={l={m=1}}}}}}}}}}}}}, tests={
174
+ { json='{"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":{"i":{"j":{"k":{"l":{"m":1}}}}}}}}}}}}}', opts={wrap=false} },
175
+ { json='{"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":{"i":{"j":{"k":{"l":{"m":1}}}}}}}}}}}}}', opts={wrap=1,short=true} },
176
+ { json="{\n \"a\":{\n \"b\":{\n \"c\":{\n \"d\":{\n \"e\":{\n \"f\":{\n \"g\":{\n \"h\":{\n \"i\":{\n \"j\":{\n \"k\":{\n \"l\":{\n \"m\":1\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}", opts={wrap=1} },
177
+ }},
178
+
179
+ {value={1,2,3,a=4,['for']=5}, tests={
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} },
182
+ }},
183
+
184
+ {value={inf=1/0, neginf=-1/0, nan=0/0}, tests={
185
+ { json='{"inf":9e9999,"nan":"NaN","neginf":-9e9999}', opts={sort=true} },
186
+ { json='{inf=1/0,nan=0/0,neginf=-1/0}', opts={sort=true, lua=true} },
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={sort=true} },
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, sort=true} },
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, sort=true} },
215
+ }},
216
+
217
+ {value={1,2,3, {bar={4,5,6}, foo={7,8,9}}}, tests={
218
+ { json='[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4,5,6],\n\t\t"foo":[7,8,9]\n\t}\n]', opts={wrap=30, sort=true, indent="\t"} },
219
+ { json='[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4.0,5.0,6.0],\n\t\t"foo":[7,8,9]\n\t}\n]', opts={wrap=30, sort=true, indent="\t", forceFloatsIn={'bar'}} },
220
+ { json='[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4,5,6],\n\t\t"foo":[7.0,8.0,9.0]\n\t}\n]', opts={wrap=30, sort=true, indent="\t", forceFloatsIn={'foo'}} },
221
+ { json='[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4.0,5.0,6.0],\n\t\t"foo":[7.0,8.0,9.0]\n\t}\n]', opts={wrap=30, sort=true, indent="\t", forceFloatsIn={'foo', 'bar'}} },
222
+ { json='[\n\t1.0,\n\t2.0,\n\t3.0,\n\t{\n\t\t"bar":[4.0,5.0,6.0],\n\t\t"foo":[7.0,8.0,9.0]\n\t}\n]', opts={wrap=30, sort=true, indent="\t", forceFloats=true} },
223
+ }},
224
+
225
+ }
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"},
@@ -174,7 +176,7 @@ TESTS = [
174
176
  { json:'{"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":{"i":{"j":{"k":{"l":{"m":1}}}}}}}}}}}}}', opts:{wrap:false} },
175
177
  { json:'{"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":{"i":{"j":{"k":{"l":{"m":1}}}}}}}}}}}}}', opts:{wrap:1,short:true} },
176
178
  { json:"{\n \"a\":{\n \"b\":{\n \"c\":{\n \"d\":{\n \"e\":{\n \"f\":{\n \"g\":{\n \"h\":{\n \"i\":{\n \"j\":{\n \"k\":{\n \"l\":{\n \"m\":1\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}", opts:{wrap:1} },
177
- ]},
179
+ ]},
178
180
 
179
181
  # Issue #27
180
182
  {value:{'b'=>2, a:1}, tests:[
@@ -184,5 +186,45 @@ TESTS = [
184
186
  {json:'{"a":1,"b":2}', opts:{wrap:false, sort:->(k,v,o){k.to_s}}},
185
187
  {json:'{"a":1,"b":2}', opts:{wrap:false, sort:true}},
186
188
  ]},
189
+
190
+ {value:{inf:1.0/0, neginf:-1.0/0, nan:0.0/0}, tests:[
191
+ { json:'{"inf":9e9999,"nan":"NaN","neginf":-9e9999}', opts:{sort:true} },
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
+ ]},
221
+
222
+ {value:[1,2,3, {bar:[4,5,6], foo:[7,8,9]}], tests:[
223
+ { json:%Q{[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4,5,6],\n\t\t"foo":[7,8,9]\n\t}\n]}, opts:{wrap:20, indent:"\t"} },
224
+ { json:%Q{[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4.0,5.0,6.0],\n\t\t"foo":[7,8,9]\n\t}\n]}, opts:{wrap:20, indent:"\t", force_floats_in:["bar"]} },
225
+ { json:%Q{[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4,5,6],\n\t\t"foo":[7.0,8.0,9.0]\n\t}\n]}, opts:{wrap:20, indent:"\t", force_floats_in:["foo"]} },
226
+ { json:%Q{[\n\t1,\n\t2,\n\t3,\n\t{\n\t\t"bar":[4.0,5.0,6.0],\n\t\t"foo":[7.0,8.0,9.0]\n\t}\n]}, opts:{wrap:20, indent:"\t", force_floats_in:["foo", "bar"]} },
227
+ { json:%Q{[\n\t1.0,\n\t2.0,\n\t3.0,\n\t{\n\t\t"bar":[4.0,5.0,6.0],\n\t\t"foo":[7.0,8.0,9.0]\n\t}\n]}, opts:{wrap:20, indent:"\t", force_floats:true} },
228
+ ]},
187
229
  ]
188
230
 
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.8.4
4
+ version: 0.10.1
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: 2018-05-03 00:00:00.000000000 Z
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
@@ -26,14 +26,16 @@ files:
26
26
  - neatjson.gemspec
27
27
  - test/large.json
28
28
  - test/test_neatjson.js
29
+ - test/test_neatjson.lua
29
30
  - test/test_neatjson.rb
30
31
  - test/tests.js
32
+ - test/tests.lua
31
33
  - test/tests.rb
32
34
  homepage: http://github.com/Phrogz/NeatJSON
33
35
  licenses:
34
36
  - MIT
35
37
  metadata: {}
36
- post_install_message:
38
+ post_install_message:
37
39
  rdoc_options: []
38
40
  require_paths:
39
41
  - lib
@@ -48,9 +50,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
48
50
  - !ruby/object:Gem::Version
49
51
  version: '0'
50
52
  requirements: []
51
- rubyforge_project:
52
- rubygems_version: 2.5.2
53
- signing_key:
53
+ rubygems_version: 3.2.3
54
+ signing_key:
54
55
  specification_version: 4
55
56
  summary: Pretty, powerful, flexible JSON generation.
56
57
  test_files: []