tidy_json 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +0 -1
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/README.md +6 -6
- data/bin/jtidy +8 -8
- data/bin/jtidy_info.rb +3 -6
- data/lib/tidy_json/formatter.rb +7 -14
- data/lib/tidy_json/serializer.rb +88 -19
- data/lib/tidy_json/version.rb +1 -1
- data/test/JsonableObject.json +1 -1
- data/test/test_tidy_json.rb +19 -15
- data/tidy_json.gemspec +3 -8
- metadata +7 -55
- data/lib/tidy_json/dedication.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c999cbe79e0f4f5436ac7038e1cd15ba1d406d3ef44c583b72a3bf393bad402
|
4
|
+
data.tar.gz: 77335cd28abcf318b87d241d2c15fce228fcc4a348a3cf0362603fb280e2bd97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2076f573353e583bd6742bb3b276b971d27460ba117b37d4ff6e62f505dce9bbb081673d5184ffe5d36a3ca84a10d18b6a97c7ddf48a0e53377d4397fa52a338
|
7
|
+
data.tar.gz: 4af6bc7b026ad1df3b107905e134c8413edd209a6804b0ac1ba2ecb5c2694bf4fefb6266e4241e86713cb55e2ab4f5d561ff2b3884995c290a6f51ac12dbf741
|
data/.yardopts
CHANGED
data/Gemfile
CHANGED
data/LICENSE
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2019-
|
3
|
+
Copyright (c) 2019-2022 Robert Di Pardo
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# tidy_json
|
2
2
|
|
3
|
-
![Gem Version][gem_version_badge] ![Downloads][gem_downloads] [![
|
3
|
+
![Gem Version][gem_version_badge] ![Downloads][gem_downloads] [![GH Actions][build_status_badge]][build_status] [![codecov][codecov_badge]][codecov_status]
|
4
4
|
|
5
5
|
A mixin providing (recursive) JSON serialization and pretty printing.
|
6
6
|
|
@@ -130,21 +130,21 @@ The `jtidy` executable bundled with this gem is in no way affiliated with, nor b
|
|
130
130
|
the HTML parser and pretty printer [of the same name](https://github.com/jtidy/jtidy).
|
131
131
|
|
132
132
|
The JTidy source code and binaries are licensed under the terms of the Zlib-Libpng License.
|
133
|
-
More information is available [here](https://
|
133
|
+
More information is available [here](https://raw.githubusercontent.com/jtidy/jtidy/master/LICENSE.txt).
|
134
134
|
|
135
135
|
### License
|
136
136
|
Distributed under the terms of the [MIT License][].
|
137
137
|
|
138
138
|
|
139
|
-
[
|
140
|
-
[
|
139
|
+
[build_status]: https://github.com/rdipardo/tidy_json/actions/workflows/tests.yml
|
140
|
+
[build_status_badge]: https://github.com/rdipardo/tidy_json/actions/workflows/tests.yml/badge.svg
|
141
141
|
[codecov_status]: https://codecov.io/gh/rdipardo/tidy_json/branch/master
|
142
142
|
[codecov_badge]: https://codecov.io/gh/rdipardo/tidy_json/branch/master/graph/badge.svg
|
143
143
|
[gem_version_badge]: https://img.shields.io/gem/v/tidy_json?color=%234ec820&label=gem%20version&logo=ruby&logoColor=%23e9573f
|
144
144
|
[gem_downloads]: https://img.shields.io/gem/dt/tidy_json?logo=ruby&logoColor=%23e9573f
|
145
|
-
[MIT License]: https://
|
145
|
+
[MIT License]: https://raw.githubusercontent.com/rdipardo/tidy_json/master/LICENSE
|
146
146
|
[installing the gem]: https://github.com/rdipardo/tidy_json#installation
|
147
147
|
<!-- API spec -->
|
148
148
|
[`JSON.generate`]: https://github.com/flori/json/blob/d49c5de49e54a5ad3f6fcf587f98d63266ef9439/lib/json/pure/generator.rb#L111
|
149
|
-
[the docs]: https://rubydoc.
|
149
|
+
[the docs]: https://rubydoc.info/github/rdipardo/tidy_json/TidyJson/Formatter#initialize-instance_method
|
150
150
|
[0.3.0]: https://github.com/rdipardo/tidy_json/releases/tag/v0.3.0
|
data/bin/jtidy
CHANGED
@@ -51,7 +51,7 @@ class Jtidy # :nodoc:
|
|
51
51
|
OPTIONS[k][0].eql? key
|
52
52
|
end.first || '')[0..1]
|
53
53
|
end
|
54
|
-
warn "Ignoring options: #{
|
54
|
+
warn "Ignoring options: #{ignored.join ', '}"
|
55
55
|
end
|
56
56
|
|
57
57
|
def self.parse(options)
|
@@ -69,7 +69,7 @@ class Jtidy # :nodoc:
|
|
69
69
|
|
70
70
|
opts.on_tail('-V', '--version', 'Show version') do
|
71
71
|
show_unused format_options
|
72
|
-
puts ::JtidyInfo.new
|
72
|
+
puts ::JtidyInfo.new
|
73
73
|
exit 0
|
74
74
|
end
|
75
75
|
|
@@ -95,7 +95,10 @@ begin
|
|
95
95
|
raise OptionParser::InvalidArgument
|
96
96
|
end
|
97
97
|
|
98
|
-
if
|
98
|
+
if INPUT_FILE.nil? || INPUT_FILE.strip.empty?
|
99
|
+
Jtidy.parse %w[--help]
|
100
|
+
|
101
|
+
else
|
99
102
|
tidy = ''
|
100
103
|
fname = INPUT_FILE.strip.gsub('\\', '/')
|
101
104
|
ext = File.extname(fname)
|
@@ -111,7 +114,7 @@ begin
|
|
111
114
|
end
|
112
115
|
|
113
116
|
begin
|
114
|
-
File.open(
|
117
|
+
File.open("#{input}.json", 'r') do |json|
|
115
118
|
begin
|
116
119
|
tidy = TidyJson.tidy(JSON.parse(json.read.strip), OPTS)
|
117
120
|
rescue JSON::JSONError => e
|
@@ -127,16 +130,13 @@ begin
|
|
127
130
|
"#{input}-tidy"
|
128
131
|
else outfile
|
129
132
|
end) + '.json'
|
130
|
-
File.
|
133
|
+
File.write(output, tidy)
|
131
134
|
puts "\nWrote: #{output}"
|
132
135
|
puts "#{tidy[0..1024]}\n . . ." if OPTS[:preview]
|
133
136
|
end
|
134
137
|
rescue Errno::ENOENT, Errno::EACCES, IOError => e
|
135
138
|
warn "#{__FILE__}.#{__LINE__}: #{e.message}"
|
136
139
|
end
|
137
|
-
|
138
|
-
else
|
139
|
-
Jtidy.parse %w[--help]
|
140
140
|
end
|
141
141
|
rescue OptionParser::InvalidArgument, OptionParser::MissingArgument
|
142
142
|
Jtidy.parse %w[--help]
|
data/bin/jtidy_info.rb
CHANGED
@@ -1,17 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module TidyJson
|
4
|
-
class JtidyInfo
|
3
|
+
module TidyJson
|
4
|
+
class JtidyInfo # :nodoc:
|
5
5
|
NOTICE = [
|
6
6
|
'#',
|
7
7
|
'# jtidy is in no way affiliated with, nor based on, ',
|
8
8
|
'# the HTML parser and pretty printer of the same name.',
|
9
9
|
'#',
|
10
|
-
'# The JTidy source code and binaries are licensed under',
|
11
|
-
'# the terms of the Zlib-Libpng License.',
|
12
|
-
'#',
|
13
10
|
'# More information is available here:',
|
14
|
-
'# https://github.com/
|
11
|
+
'# https://github.com/rdipardo/tidy_json#command-line-usage',
|
15
12
|
'#'
|
16
13
|
].join("\n").freeze
|
17
14
|
|
data/lib/tidy_json/formatter.rb
CHANGED
@@ -80,10 +80,8 @@ module TidyJson
|
|
80
80
|
indent = @format[:indent]
|
81
81
|
|
82
82
|
is_last = (obj.length <= 1) ||
|
83
|
-
(obj.
|
84
|
-
(obj.
|
85
|
-
!(node === obj.first) &&
|
86
|
-
(obj.size.pred == obj.rindex(node))))
|
83
|
+
(obj.instance_of?(Array) &&
|
84
|
+
(obj.size.pred == obj.rindex(node)))
|
87
85
|
|
88
86
|
if node.instance_of?(Array)
|
89
87
|
str << '['
|
@@ -132,12 +130,7 @@ module TidyJson
|
|
132
130
|
node.each_with_index do |h, idx|
|
133
131
|
# format values which are hashes themselves
|
134
132
|
if h.last.instance_of?(Hash)
|
135
|
-
key =
|
136
|
-
"#{indent * 2}\"<##{h.last.class.name.downcase}>\": "
|
137
|
-
else
|
138
|
-
"#{indent * 2}\"#{h.first}\": "
|
139
|
-
end
|
140
|
-
|
133
|
+
key = "#{indent * 2}\"#{h.first || "<##{h.last.class.name.downcase}>"}\": "
|
141
134
|
str << key << '{'
|
142
135
|
str << "\n" unless h.last.empty?
|
143
136
|
|
@@ -171,8 +164,8 @@ module TidyJson
|
|
171
164
|
end
|
172
165
|
|
173
166
|
trim str.gsub(/(#{indent})+[\n\r]+/, '')
|
174
|
-
.gsub(/\}
|
175
|
-
.gsub(/\]
|
167
|
+
.gsub(/\},+/, '},')
|
168
|
+
.gsub(/\],+/, '],')
|
176
169
|
end
|
177
170
|
# ~Formatter#format_node
|
178
171
|
|
@@ -210,7 +203,7 @@ module TidyJson
|
|
210
203
|
|
211
204
|
elsif !node.instance_of?(String) then graft << node.to_s
|
212
205
|
|
213
|
-
else graft << "\"#{node.gsub(
|
206
|
+
else graft << "\"#{node.gsub('"', '\\"')}\""
|
214
207
|
end
|
215
208
|
|
216
209
|
graft.strip
|
@@ -223,7 +216,7 @@ module TidyJson
|
|
223
216
|
# @param node [String] A serialized object member.
|
224
217
|
# @return [String] A copy of +node+ without a trailing comma.
|
225
218
|
def trim(node)
|
226
|
-
if (extra_comma = /(?<trail>,\s*[\]
|
219
|
+
if (extra_comma = /(?<trail>,\s*[\]}]\s*)$/.match(node))
|
227
220
|
node.sub(extra_comma[:trail],
|
228
221
|
extra_comma[:trail]
|
229
222
|
.slice(1, node.length.pred)
|
data/lib/tidy_json/serializer.rb
CHANGED
@@ -7,15 +7,93 @@ module TidyJson
|
|
7
7
|
# @api private
|
8
8
|
class Serializer
|
9
9
|
##
|
10
|
-
# Searches +obj+
|
11
|
-
#
|
10
|
+
# Searches +obj+ for readable attributes, storing them as key-value pairs in
|
11
|
+
# +json_hash+.
|
12
12
|
#
|
13
13
|
# @param obj [Object] A Ruby object that can be parsed as JSON.
|
14
14
|
# @param json_hash [{String,Symbol => #to_s}] Accumulator.
|
15
15
|
# @return [{String => #to_s}] A hash mapping of +obj+'s visible attributes.
|
16
|
+
# @note Hashes will be searched for nested objects to a maximum depth of 2;
|
17
|
+
# arrays to a maximum depth of 3.
|
18
|
+
# @example
|
19
|
+
# class Obj
|
20
|
+
# class Child
|
21
|
+
# def initialize; @a = { a: 1 } end
|
22
|
+
# attr_reader :a
|
23
|
+
# end
|
24
|
+
# def initialize; @a = { b: Child.new } end
|
25
|
+
# attr_accessor :a
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# o = Obj.new
|
29
|
+
# puts o.to_tidy_json
|
30
|
+
# <<JSON
|
31
|
+
# {
|
32
|
+
# "class": "Obj",
|
33
|
+
# "a": {
|
34
|
+
# "b": {
|
35
|
+
# "class": "Obj::Child",
|
36
|
+
# "a": {
|
37
|
+
# "a": 1
|
38
|
+
# }
|
39
|
+
# }
|
40
|
+
# }
|
41
|
+
# }
|
42
|
+
# JSON
|
43
|
+
#
|
44
|
+
# # depth > 2: unreachable objects are not serialized
|
45
|
+
# o.a = { b: { c: { d: Obj::Child.new } } }
|
46
|
+
# puts o.to_tidy_json
|
47
|
+
# <<JSON
|
48
|
+
# {
|
49
|
+
# "class": "Obj",
|
50
|
+
# "a": {
|
51
|
+
# "b": {
|
52
|
+
# "c": {
|
53
|
+
# "d": "#<Obj::Child:0x0000559d4da865c0>"
|
54
|
+
# }
|
55
|
+
# }
|
56
|
+
# }
|
57
|
+
# }
|
58
|
+
# JSON
|
59
|
+
#
|
60
|
+
# # object arrays can be nested up to 3 levels deep
|
61
|
+
# o.a = [ [ Obj::Child.new, [ Obj::Child.new, [ Obj::Child.new ] ] ] ]
|
62
|
+
# puts o.to_tidy_json
|
63
|
+
# <<JSON
|
64
|
+
# {
|
65
|
+
# "class": "Obj",
|
66
|
+
# "a": [
|
67
|
+
# {
|
68
|
+
# "class": "Obj::Child",
|
69
|
+
# "a": {
|
70
|
+
# "a": 1
|
71
|
+
# }
|
72
|
+
# },
|
73
|
+
# [
|
74
|
+
# [
|
75
|
+
# {
|
76
|
+
# "class": "Obj::Child",
|
77
|
+
# "a": {
|
78
|
+
# "a": 1
|
79
|
+
# }
|
80
|
+
# },
|
81
|
+
# [
|
82
|
+
# {
|
83
|
+
# "class": "Obj::Child",
|
84
|
+
# "a": {
|
85
|
+
# "a": 1
|
86
|
+
# }
|
87
|
+
# }
|
88
|
+
# ]
|
89
|
+
# ]
|
90
|
+
# ]
|
91
|
+
# ]
|
92
|
+
# }
|
93
|
+
# JSON
|
16
94
|
def self.serialize(obj, json_hash)
|
17
95
|
obj.instance_variables.each do |m|
|
18
|
-
key = m.to_s[/[
|
96
|
+
key = m.to_s[/[^@]\w*/].to_sym
|
19
97
|
|
20
98
|
next unless key && !key.eql?('')
|
21
99
|
|
@@ -28,24 +106,10 @@ module TidyJson
|
|
28
106
|
begin
|
29
107
|
# process class members of Hash type
|
30
108
|
if val.instance_of?(Hash)
|
31
|
-
nested_key = ''
|
32
|
-
nested = nil
|
33
|
-
|
34
|
-
val.each.any? do |k, v|
|
35
|
-
unless v.instance_variables.empty?
|
36
|
-
nested_key = k
|
37
|
-
nested = v
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
109
|
json_hash[key] = val
|
42
110
|
|
43
|
-
|
44
|
-
|
45
|
-
nested.instance_variables.each do
|
46
|
-
json_hash[key][pos] = serialize(nested,
|
47
|
-
class: nested.class.name)
|
48
|
-
end
|
111
|
+
val.each.any? do |k, v|
|
112
|
+
json_hash[key][k.to_sym] = serialize(v, class: v.class.name) unless v.instance_variables.empty?
|
49
113
|
end
|
50
114
|
|
51
115
|
# process class members of Array type
|
@@ -75,6 +139,11 @@ module TidyJson
|
|
75
139
|
elsif e.respond_to?(:each)
|
76
140
|
temp = []
|
77
141
|
e.each do |el|
|
142
|
+
if el.respond_to?(:each)
|
143
|
+
el.each_with_index do |ell, idx|
|
144
|
+
el[idx] = serialize(ell, class: ell.class.name) unless ell.instance_variables.empty?
|
145
|
+
end
|
146
|
+
end
|
78
147
|
temp << if el.instance_variables.empty? then el
|
79
148
|
else JSON.parse(el.stringify)
|
80
149
|
end
|
data/lib/tidy_json/version.rb
CHANGED