tidy_json 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5c8377fc4c17ae11f718b6cadd5a0bbf5a806c1706f8184370e036dbeb714d73
4
+ data.tar.gz: dd9dcac5f8b3294f1edbd7a05762ad89277e6b593b0610d79d501e3d68e62fea
5
+ SHA512:
6
+ metadata.gz: 62b421c64ac5ecbd6fcc54a9e43f57d1e04ae52b6b6ab21c5eb65d65b4a267e44a28dde2ee67cf80167c5d0857c242c246e3881d510f00493e44b835fb17b52a
7
+ data.tar.gz: 0b7534efee7f35486f1bc8f60dab7031f762aa6fdc69a7eb83d603b2cfae25583aa702e4009ff8dba284a0e1b3136e0c4bafe39f43e235951d7bc93a767eca1a
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --private lib/*.rb lib/tidy_json/version.rb - README.md LICENSE
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rake'
7
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Robert Di Pardo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # TidyJson
2
+
3
+ [![Build Status](https://travis-ci.com/rdipardo/tidy_json.svg)](https://travis-ci.com/rdipardo/tidy_json)
4
+
5
+ A mixin providing (recursive) JSON serialization and pretty printing.
6
+
7
+ ### Installation
8
+
9
+ #### Minimal
10
+
11
+ ```bash
12
+ $ gem install tidy_json
13
+ ```
14
+
15
+ #### Development (tests, YARD docs)
16
+
17
+ ```bash
18
+ $ gem install -​-development tidy_json
19
+ ```
20
+
21
+ Or, with `bundler`:
22
+
23
+ ```ruby
24
+ source 'https://rubygems.org'
25
+ # ...
26
+ gem 'tidy_json'
27
+ # ...
28
+ ```
29
+
30
+ ### Example
31
+
32
+ ```ruby
33
+ require 'tidy_json'
34
+
35
+ JSON.parse [].stringify
36
+ # => {"class"=>"Array"}
37
+
38
+ complex_object = { :a => 1, :b => ['two', 3, '<abbr title="four">IV</abbr>'] }
39
+ # => {:a=>1, :b=>["two", 3, "<abbr title=\"four\">IV</abbr>"]}
40
+
41
+ puts complex_object.to_tidy_json
42
+ # {
43
+ # "a": 1,
44
+ # "b":
45
+ # [
46
+ # "two",
47
+ # 3,
48
+ # "<abbr title=\"four\">IV</abbr>"
49
+ # ]
50
+ # }
51
+ # => nil
52
+ ```
53
+
54
+ ### Dependencies
55
+
56
+ #### Runtime
57
+ - [json](https://rubygems.org/gems/json) ~> 2.2
58
+
59
+ #### Building
60
+ - [bundler](https://rubygems.org/gems/bundler) ~> 2.1
61
+ - [minitest](https://rubygems.org/gems/minitest) ~> 5.0
62
+ - [yard](https://rubygems.org/gems/yard) ~> 0.9
63
+
64
+ ### License
65
+ [MIT](https://opensource.org/licenses/MIT)
66
+
67
+ ### Author
68
+ [Robert Di Pardo](mailto:rdipardo0520@conestogac.on.ca)
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'yard'
4
+
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.libs << 'test'
7
+ t.libs << 'lib'
8
+ t.test_files = FileList['test/**/test_*.rb']
9
+ end
10
+
11
+ YARD::Rake::YardocTask.new
12
+
13
+ desc 'Run tests'
14
+ task default: :test
@@ -0,0 +1,11 @@
1
+ module TidyJson # :nodoc:
2
+ DEDICATION = "#{'.' * 50}\n#{'.' * 20} tidy_json #{'.' * 19}\n" \
3
+ "#{'.' * 12} (c) 2019 Robert Di Pardo #{'.' * 12}\n" \
4
+ "#{'.' * 50}\n#{'.' * 19} IN MEMORIAM #{'.' * 18}\n" \
5
+ "#{'.' * 16} Michael Di Pardo #{'.' * 16}\n" \
6
+ "#{'.' * 19} 1950 - 2019 #{'.' * 18}\n#{'.' * 50}\n" \
7
+ "#{'.' * 12} Please consider supporting #{'.' * 11}\n" \
8
+ "#{'.' * 13} the MS Society of Canada #{'.' * 11}\n" \
9
+ "#{'.' * 8} https://mssociety.ca/get-involved #{'.' * 7}\n" \
10
+ "#{'.' * 50}\n"
11
+ end
@@ -0,0 +1,3 @@
1
+ module TidyJson
2
+ VERSION = '0.1.1'
3
+ end
data/lib/tidy_json.rb ADDED
@@ -0,0 +1,384 @@
1
+ require 'json'
2
+ require_relative 'tidy_json/version'
3
+
4
+ ##
5
+ # A mixin providing (recursive) JSON serialization and pretty printing.
6
+ #
7
+ module TidyJson
8
+ ##
9
+ # Emits a pretty-printed JSON representation of the given +obj+.
10
+ #
11
+ # @param obj [Object] A Ruby object that can be parsed as JSON.
12
+ # @return [String] A pretty-printed JSON string.
13
+ def self.tidy(obj = {})
14
+ str = ''
15
+
16
+ if obj.instance_of?(Hash)
17
+ str << "{\n"
18
+
19
+ obj.each do |k, v|
20
+ str << "\"#{k}\": "
21
+ str << Serializer.format_node(v, obj)
22
+ end
23
+
24
+ str << "}\n"
25
+
26
+ elsif obj.instance_of?(Array)
27
+ str << "[\n"
28
+
29
+ obj.each do |v|
30
+ str << Serializer.format_node(v, obj)
31
+ end
32
+
33
+ str << "]\n"
34
+ end
35
+
36
+ str
37
+ end
38
+
39
+ ##
40
+ # Like +TidyJson::tidy+, but callable by the sender object with the option *not* to pretty-print.
41
+ #
42
+ # @param pretty [Boolean] Whether or not the returned string should be pretty-printed.
43
+ # @return [String] A pretty-printed JSON string.
44
+ def to_tidy_json(pretty = true)
45
+ if !instance_variables.empty?
46
+ if pretty then TidyJson.tidy(JSON.parse(stringify))
47
+ else stringify
48
+ end
49
+ else
50
+ if pretty then TidyJson.tidy(self)
51
+ else to_json
52
+ end
53
+ end
54
+ end
55
+
56
+ ##
57
+ # Emits a JSON representation of the sender object's visible attributes.
58
+ #
59
+ # @return [String] A raw JSON string.
60
+ def stringify
61
+ json_hash = {}
62
+
63
+ begin
64
+ json_hash = Serializer.serialize(self, class: self.class.name)
65
+ rescue JSON::JSONError => e
66
+ warn "#{__FILE__}.#{__LINE__}: #{e.message}"
67
+ end
68
+
69
+ json_hash.to_json
70
+ end
71
+
72
+ ##
73
+ # Writes a pretty-printed JSON representation of the sender object to the file specified by +out+.
74
+ #
75
+ # @param pretty [Boolean] Whether or not the output should be pretty-printed.
76
+ # @param out [String] The destination filename. Defaults to <tt><obj_class_name>_<current_UNIX_time></tt>.json
77
+ # @return [String, nil] The path to the written output file, if successful.
78
+ def write_json(pretty = true, out = "#{self.class.name}_#{Time.now.to_i}")
79
+ path = nil
80
+
81
+ File.open("#{out}.json", 'w') do |f|
82
+ path = f << to_tidy_json(pretty)
83
+ end
84
+
85
+ path.path
86
+ rescue IOError, RuntimeError, NoMethodError => e
87
+ warn "#{__FILE__}.#{__LINE__}: #{e.message}"
88
+ end
89
+
90
+ ##
91
+ # A purpose-built JSON generator.
92
+ #
93
+ # @api private
94
+ class Serializer
95
+ ##
96
+ # The number of times to reduce the left margin of a nested array's opening
97
+ # bracket
98
+ @margins_to_backspace = 0
99
+
100
+ ##
101
+ # True if printing a nested array
102
+ @should_backspace = false
103
+
104
+ ##
105
+ # Searches +obj+ to a *maximum* depth of 2 for readable attributes,
106
+ # storing them as key-value pairs in +json_hash+.
107
+ #
108
+ # @param obj [Object] A Ruby object that can be parsed as JSON.
109
+ # @param json_hash [{String,Symbol => #to_s}] Accumulator.
110
+ # @return [{String => #to_s}] A hash mapping of +obj+'s visible attributes.
111
+ def self.serialize(obj, json_hash)
112
+ obj.instance_variables.each do |m|
113
+ key = m.to_s[/[^\@]\w*/].to_sym
114
+
115
+ next unless key && !key.eql?('')
116
+
117
+ begin
118
+ val = obj.send(key) # assuming readable attributes . . .
119
+ rescue NoMethodError # . . . which may not be always be the case !
120
+ json_hash[key] = nil
121
+ end
122
+
123
+ begin
124
+ # process class members of Hash type
125
+ if val.instance_of?(Hash)
126
+ nested_key = ''
127
+ nested = nil
128
+
129
+ val.each.any? do |k, v|
130
+ if v.instance_variables.first
131
+ nested_key = k
132
+ nested = v
133
+ end
134
+ end
135
+
136
+ json_hash[key] = val
137
+
138
+ if nested
139
+ pos = val.keys.select { |k| k === nested_key }.first.to_sym
140
+ nested.instance_variables.each do
141
+ json_hash[key][pos] = serialize(nested, class: nested.class.name)
142
+ end
143
+ end
144
+
145
+ # process class members of Array type
146
+ elsif val.instance_of?(Array)
147
+ json_hash[key] = []
148
+
149
+ val.each do |elem|
150
+ i = val.index(elem)
151
+
152
+ # multi-dimensional array
153
+ if elem.instance_of?(Array)
154
+ nested = []
155
+ elem.each do |e|
156
+ j = elem.index(e)
157
+
158
+ # nested array element is a class object
159
+ if e.instance_variables.first
160
+ json_hash[key][j] = { class: e.class.name }
161
+
162
+ # recur over the contained object
163
+ serialize(e, json_hash[key][j])
164
+ else
165
+ # some kind of collection?
166
+ if e.respond_to? :each
167
+ temp = []
168
+ e.each { |el| temp << el }
169
+ nested << temp
170
+ else nested << e
171
+ end
172
+ end
173
+ end
174
+ # ~iteration of nested array elements
175
+
176
+ json_hash[key] << nested
177
+
178
+ else
179
+ # 1-D array of class objects
180
+ if elem.instance_variables.first
181
+ json_hash[key] << { class: elem.class.name }
182
+ serialize(elem, json_hash[key][i])
183
+ else
184
+ # element of primitive type (or Array, or Hash):
185
+ # leverage 1:1 mapping of Hash:object
186
+ if elem.instance_of?(Hash) then json_hash[key] = val
187
+ else
188
+ # some kind of collection
189
+ if elem.respond_to? :each
190
+ temp = []
191
+ elem.each { |e| temp << e }
192
+ json_hash[key] << temp
193
+ else json_hash[key] << elem
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
199
+ # ~iteration of top-level array elements
200
+
201
+ # process any nested class members, i.e., handle a recursive call
202
+ # to Serializer.serialize
203
+ elsif obj.index(val) || json_hash.key?(key)
204
+ if val.instance_variables.first
205
+ class_elem = { class: val.class.name }
206
+ json_hash[key] << class_elem
207
+ k = json_hash[key].index(class_elem)
208
+ serialize(val, json_hash[key][k])
209
+ else
210
+ json_hash[key] << val
211
+ end
212
+
213
+ # process uncollected data members
214
+ else
215
+ # member a class object
216
+ if val.instance_variables.first
217
+ json_hash[key] = { class: val.class.name }
218
+ serialize(val, json_hash[key])
219
+ else
220
+ # member a hash element
221
+ if json_hash.key?(key) && \
222
+ !json_hash[key].has_val?(val) && \
223
+ json_hash[key].instance_of?(Hash)
224
+
225
+ json_hash[key][key] = val
226
+ else
227
+ json_hash[key] = val
228
+ end
229
+ end
230
+ end
231
+ rescue NoMethodError
232
+ # we expected an array to behave like a hash, or vice-versa
233
+ json_hash.store(key, val) # a shallow copy is better than nothing
234
+ end
235
+ end
236
+ # ~iteration of instance variables
237
+
238
+ json_hash
239
+ end
240
+ # ~Serializer.serialize
241
+
242
+ ##
243
+ # Returns the given +node+ as pretty-printed JSON.
244
+ #
245
+ # @param node [#to_s] A visible attribute of +obj+.
246
+ # @param obj [{Object => Object}, <Object>] The enumerable object containing +node+.
247
+ # @return [String] A formatted string representation of +node+.
248
+ def self.format_node(node, obj)
249
+ str = ''
250
+
251
+ if node.instance_of?(Array)
252
+ str << "\n\t[\n"
253
+
254
+ node.each do |elem|
255
+ if elem.instance_of?(Hash)
256
+ str << "\t\t{\n"
257
+
258
+ elem.each_with_index do |inner_h, h_idx|
259
+ str << "\t\t\t\"#{inner_h.first}\":"
260
+ str << node_to_str(inner_h.last)
261
+ str << ', ' unless h_idx == (elem.to_a.length - 1)
262
+ str << "\n"
263
+ end
264
+
265
+ str << "\t\t}"
266
+ str << ',' unless node.index(elem) == (node.length - 1)
267
+ str << "\n" unless node.index(elem) == (node.length - 1)
268
+
269
+ else
270
+
271
+ if elem.instance_of?(Array) && elem.any? { |e| e.instance_of?(Array) }
272
+ @margins_to_backspace = elem.take_while { |e| e.instance_of?(Array) }.size
273
+ end
274
+
275
+ str << "\t\t"
276
+ str << node_to_str(elem)
277
+ str << ",\n" unless node.index(elem) == (node.length - 1)
278
+ end
279
+ end
280
+
281
+ str << "\n\t]\n"
282
+
283
+ elsif node.instance_of?(Hash)
284
+ str << "\n\t{\n"
285
+
286
+ node.each_with_index do |h, idx|
287
+ if h.last.instance_of?(Hash)
288
+ key = if h.first.eql? ''
289
+ "\t\t\"<##{h.last.class.name.downcase}>\":"
290
+ else
291
+ "\t\t\"#{h.first}\":"
292
+ end
293
+ str << key
294
+ str << "\n\t\t\t{\n"
295
+
296
+ h.last.each_with_index do |inner_h, inner_h_idx|
297
+ str << "\t\t\t\t\"#{inner_h.first}\":"
298
+ str << node_to_str(inner_h.last, 4)
299
+ str << ",\n" unless inner_h_idx == (h.last.to_a.length - 1)
300
+ end
301
+
302
+ str << "\n\t\t\t}"
303
+ else
304
+ str << "\t\t\"#{h.first}\": "
305
+ str << node_to_str(h.last)
306
+ end
307
+
308
+ str << ",\n" unless idx == (node.to_a.length - 1)
309
+ end
310
+
311
+ str << "\n\t}"
312
+ str << ', ' unless (obj.length <= 1) || \
313
+ ((obj.length > 1) && \
314
+ (obj.instance_of?(Hash) && \
315
+ (obj.key(obj.values.last) === obj.key(node))) || \
316
+ (obj.instance_of?(Array) && (obj.last == node)))
317
+ str << "\n"
318
+
319
+ else
320
+ str << node_to_str(node)
321
+ str << ', ' unless (obj.length <= 1) || \
322
+ ((obj.length > 1) && \
323
+ (obj.instance_of?(Hash) && \
324
+ (obj.key(obj.values.last) === obj.key(node))) || \
325
+ (obj.instance_of?(Array) && (obj.last === node)))
326
+ str << "\n"
327
+ end
328
+
329
+ str.gsub(/\t+[\n\r]+/, '').gsub(/\}\,+/, '},').gsub(/\]\,+/, '],')
330
+ end
331
+ # ~Serializer.format_node
332
+
333
+ ##
334
+ # Returns a JSON-appropriate string representation of +node+.
335
+ #
336
+ # @param node [#to_s] A visible attribute of a Ruby object.
337
+ # @param tabs [Fixnum] Tab width at which to start printing this node.
338
+ # @return [String] A formatted string representation of +node+.
339
+ def self.node_to_str(node, tabs = 0)
340
+ graft = ''
341
+
342
+ tabs += 2 if tabs.zero?
343
+ if @should_backspace
344
+ tabs -= 1
345
+ @margins_to_backspace -= 1
346
+ end
347
+
348
+ if node.nil? then graft << 'null'
349
+ elsif node.instance_of?(Hash)
350
+
351
+ format_node(node, node).scan(/.*$/) do |n|
352
+ graft << "\n" << ("\t" * tabs).to_s << n
353
+ end
354
+
355
+ elsif node.instance_of?(Array)
356
+ @should_backspace = @margins_to_backspace.positive?
357
+
358
+ format_node(node, {}).scan(/.*$/) do |n|
359
+ graft << "\n" << ("\t" * tabs).to_s << n
360
+ end
361
+
362
+ elsif !node.instance_of?(String) then graft << node.to_s
363
+ else graft << "\"#{node.gsub(/\"/, '\\"')}\""
364
+ end
365
+
366
+ graft.rstrip
367
+ end
368
+ # ~Serializer.node_to_str
369
+ end
370
+ # ~Serializer
371
+
372
+ private_constant :Serializer
373
+ end
374
+ # ~TidyJson
375
+
376
+ ##
377
+ # Exposes the +TidyJson+ mixin to all Ruby objects.
378
+ # ====
379
+ # class Object
380
+ # include TidyJson
381
+ # end
382
+ class Object
383
+ include TidyJson
384
+ end
@@ -0,0 +1,49 @@
1
+ require 'minitest/autorun'
2
+ require 'tidy_json'
3
+
4
+ ##
5
+ # Tests.
6
+ #
7
+ class JsonableObject
8
+ attr_reader(:h, :a)
9
+
10
+ def initialize
11
+ @h = { one: 'uno', two: 'dos', three: %w[eine zwei drei], cuatro: ['I', 'II', 'III', ['i.', 'ii.', 'iii.', 'iv.']] }
12
+ @a = ['k', 'l', %w[M N O P], 'q', 'r', 's', [10, 456, ['<abbr title="Reel 2, Dialog Track 2">R2D2</abbr>', 'R', 2, 'D', ['two']]], 'u', 'v', 'x', 'y', %w[Z AB]]
13
+ end
14
+ end
15
+
16
+ class TidyJsonTest < Minitest::Test
17
+ @@t = JsonableObject.new
18
+ @@t2 = JsonableObject.new
19
+ @@t3 = JsonableObject.new
20
+ @@t.h[:cinque] = { 'ichi' => "\u{4e00}", 'ni' => "\u{4e8c}", 'san' => "\u{4e09}", 'yon' => "\u{56db}" }
21
+ @@t.h[:sei] = @@t2
22
+ @@t2.h[:five] = @@t3
23
+ @@t.a.unshift([@@t2, 13, 14, 15, 5.6])
24
+
25
+ def test_version_number
26
+ refute_nil ::TidyJson::VERSION
27
+ end
28
+
29
+ def test_tidy_static
30
+ assert_equal(TidyJson.tidy(a: 'one', A: 'ONE', b: nil), "{\n\"a\": \"one\", \n\"A\": \"ONE\", \n\"b\": null\n}\n")
31
+ assert_equal(TidyJson.tidy({}).length, 4)
32
+ end
33
+
34
+ def test_tidy_instance
35
+ assert_equal({}.to_tidy_json, "{\n}\n")
36
+ assert_equal(JsonableObject.new.to_tidy_json.length, 568)
37
+ end
38
+
39
+ def test_stringify_instance
40
+ assert_equal(@@t.stringify, "{\"class\":\"JsonableObject\",\"h\":{\"one\":\"uno\",\"two\":\"dos\",\"three\":[\"eine\",\"zwei\",\"drei\"],\"cuatro\":[\"I\",\"II\",\"III\",[\"i.\",\"ii.\",\"iii.\",\"iv.\"]],\"cinque\":{\"ichi\":\"\u{4e00}\",\"ni\":\"\u{4e8c}\",\"san\":\"\u{4e09}\",\"yon\":\"\u{56db}\"},\"sei\":{\"class\":\"JsonableObject\",\"h\":{\"one\":\"uno\",\"two\":\"dos\",\"three\":[\"eine\",\"zwei\",\"drei\"],\"cuatro\":[\"I\",\"II\",\"III\",[\"i.\",\"ii.\",\"iii.\",\"iv.\"]],\"five\":{\"class\":\"JsonableObject\",\"h\":{\"one\":\"uno\",\"two\":\"dos\",\"three\":[\"eine\",\"zwei\",\"drei\"],\"cuatro\":[\"I\",\"II\",\"III\",[\"i.\",\"ii.\",\"iii.\",\"iv.\"]]},\"a\":[\"k\",\"l\",[\"M\",\"N\",\"O\",\"P\"],\"q\",\"r\",\"s\",[10,456,[\"<abbr title=\\\"Reel 2, Dialog Track 2\\\">R2D2</abbr>\",\"R\",2,\"D\",[\"two\"]]],\"u\",\"v\",\"x\",\"y\",[\"Z\",\"AB\"]]}},\"a\":[\"k\",\"l\",[\"M\",\"N\",\"O\",\"P\"],\"q\",\"r\",\"s\",[10,456,[\"<abbr title=\\\"Reel 2, Dialog Track 2\\\">R2D2</abbr>\",\"R\",2,\"D\",[\"two\"]]],\"u\",\"v\",\"x\",\"y\",[\"Z\",\"AB\"]]}},\"a\":[{\"class\":\"JsonableObject\",\"h\":{\"one\":\"uno\",\"two\":\"dos\",\"three\":[\"eine\",\"zwei\",\"drei\"],\"cuatro\":[\"I\",\"II\",\"III\",[\"i.\",\"ii.\",\"iii.\",\"iv.\"]],\"five\":{\"class\":\"JsonableObject\",\"h\":{\"one\":\"uno\",\"two\":\"dos\",\"three\":[\"eine\",\"zwei\",\"drei\"],\"cuatro\":[\"I\",\"II\",\"III\",[\"i.\",\"ii.\",\"iii.\",\"iv.\"]]},\"a\":[\"k\",\"l\",[\"M\",\"N\",\"O\",\"P\"],\"q\",\"r\",\"s\",[10,456,[\"<abbr title=\\\"Reel 2, Dialog Track 2\\\">R2D2</abbr>\",\"R\",2,\"D\",[\"two\"]]],\"u\",\"v\",\"x\",\"y\",[\"Z\",\"AB\"]]}},\"a\":[\"k\",\"l\",[\"M\",\"N\",\"O\",\"P\"],\"q\",\"r\",\"s\",[10,456,[\"<abbr title=\\\"Reel 2, Dialog Track 2\\\">R2D2</abbr>\",\"R\",2,\"D\",[\"two\"]]],\"u\",\"v\",\"x\",\"y\",[\"Z\",\"AB\"]]},[13,14,15,5.6],\"k\",\"l\",[\"M\",\"N\",\"O\",\"P\"],\"q\",\"r\",\"s\",[10,456,[\"<abbr title=\\\"Reel 2, Dialog Track 2\\\">R2D2</abbr>\",\"R\",2,\"D\",[\"two\"]]],\"u\",\"v\",\"x\",\"y\",[\"Z\",\"AB\"]]}")
41
+ end
42
+
43
+ def test_writers
44
+ output = @@t.write_json(false)
45
+ assert(File.exist?(output))
46
+ pretty_output = @@t.write_json(true, 'prettified')
47
+ assert(File.exist?(pretty_output))
48
+ end
49
+ end
data/tidy_json.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ require_relative 'lib/tidy_json/version'
2
+ require_relative 'lib/tidy_json/dedication'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = 'tidy_json'
6
+ spec.version = TidyJson::VERSION
7
+ spec.date = Time.now.to_s[0..9].to_s
8
+ spec.summary = 'Serialize any Ruby object as readable JSON'
9
+ spec.description = 'A mixin providing (recursive) JSON serialization and pretty printing.'
10
+ spec.authors = ['Robert Di Pardo']
11
+ spec.email = 'rdipardo0520@conestogac.on.ca'
12
+ spec.homepage = 'https://github.com/rdipardo/tidy_json'
13
+ spec.license = 'MIT'
14
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
15
+ ['.yardopts'].concat(`git ls-files -z`.split("\x0").reject { |f| f.match(/^(\.[\w+\.]+|test|spec|features)/) })
16
+ end
17
+ spec.test_files = Dir['test/*']
18
+ spec.require_paths = ['lib']
19
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
20
+ spec.add_runtime_dependency 'json', '~> 2.2'
21
+ spec.add_development_dependency 'bundler', '~> 2.1'
22
+ spec.add_development_dependency 'minitest', '~> 5.0'
23
+ spec.add_development_dependency 'yard', '~> 0.9'
24
+ spec.rdoc_options = ['-x test/*']
25
+ spec.post_install_message = TidyJson::DEDICATION
26
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tidy_json
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Robert Di Pardo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-12-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.9'
69
+ description: A mixin providing (recursive) JSON serialization and pretty printing.
70
+ email: rdipardo0520@conestogac.on.ca
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - ".yardopts"
76
+ - Gemfile
77
+ - LICENSE
78
+ - README.md
79
+ - Rakefile
80
+ - lib/tidy_json.rb
81
+ - lib/tidy_json/dedication.rb
82
+ - lib/tidy_json/version.rb
83
+ - test/test_tidy_json.rb
84
+ - tidy_json.gemspec
85
+ homepage: https://github.com/rdipardo/tidy_json
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message: |
90
+ ..................................................
91
+ .................... tidy_json ...................
92
+ ............ (c) 2019 Robert Di Pardo ............
93
+ ..................................................
94
+ ................... IN MEMORIAM ..................
95
+ ................ Michael Di Pardo ................
96
+ ................... 1950 - 2019 ..................
97
+ ..................................................
98
+ ............ Please consider supporting ...........
99
+ ............. the MS Society of Canada ...........
100
+ ........ https://mssociety.ca/get-involved .......
101
+ ..................................................
102
+ rdoc_options:
103
+ - "-x test/*"
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 2.3.0
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubygems_version: 3.1.1
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: Serialize any Ruby object as readable JSON
121
+ test_files:
122
+ - test/test_tidy_json.rb