xjson 0.1
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 +7 -0
- data/CHANGELOG.rdoc +3 -0
- data/LICENSE +20 -0
- data/README.rdoc +3 -0
- data/doc/Xjson.html +1577 -0
- data/doc/Xjson/XjsonIncludeError.html +124 -0
- data/doc/Xjson/XjsonReferenceError.html +124 -0
- data/doc/_index.html +124 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +496 -0
- data/doc/file.CHANGELOG.html +76 -0
- data/doc/file.README.html +74 -0
- data/doc/file_list.html +61 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +74 -0
- data/doc/js/app.js +314 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +187 -0
- data/doc/top-level-namespace.html +110 -0
- data/lib/xjson.rb +268 -0
- data/test/golden/test.json +66 -0
- data/test/input/inc-arr.ext.json +4 -0
- data/test/input/inc-hash.ext.json +4 -0
- data/test/input/test.ext.json +34 -0
- data/test/test_xjson.rb +44 -0
- metadata +71 -0
data/lib/xjson.rb
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
require 'json'
|
2
|
+
# require 'byebug'
|
3
|
+
|
4
|
+
class Xjson
|
5
|
+
|
6
|
+
class XjsonIncludeError < RuntimeError; end
|
7
|
+
class XjsonReferenceError < RuntimeError; end
|
8
|
+
|
9
|
+
VERSION = "0.0.1"
|
10
|
+
def Xjson.version
|
11
|
+
Xjson::VERSION
|
12
|
+
end
|
13
|
+
|
14
|
+
def Xjson.load( filename )
|
15
|
+
Marshal.load( File.read( filename ) )
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :ext_data
|
19
|
+
attr_reader :data
|
20
|
+
attr_reader :dir
|
21
|
+
|
22
|
+
def initialize( xjson_file )
|
23
|
+
@cur_file = []
|
24
|
+
@cur_data = []
|
25
|
+
@ext_data = {}
|
26
|
+
@ext_data = read_json_file( xjson_file )
|
27
|
+
@data = expand( @ext_data )
|
28
|
+
end
|
29
|
+
|
30
|
+
def read_json_file( xjson_file )
|
31
|
+
@cur_file.unshift xjson_file
|
32
|
+
if xjson_file[0] != "<"
|
33
|
+
JSON.parse( File.read( xjson_file ) )
|
34
|
+
else
|
35
|
+
JSON.parse( STDIN.read )
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Flatten by one level within array.
|
40
|
+
def flatten( data )
|
41
|
+
case data
|
42
|
+
when Array;
|
43
|
+
res = []
|
44
|
+
data.each do |i|
|
45
|
+
if i.class == Array
|
46
|
+
res += i
|
47
|
+
else
|
48
|
+
res.push i
|
49
|
+
end
|
50
|
+
end
|
51
|
+
res
|
52
|
+
else
|
53
|
+
data
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def find_in_array_of_hash( scope, key, value )
|
58
|
+
index = 0
|
59
|
+
while index < scope.length
|
60
|
+
if Regexp.new( value).match( scope[ index ][ key ] )
|
61
|
+
return index
|
62
|
+
end
|
63
|
+
index += 1
|
64
|
+
end
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def reference_handle( data, ref_desc )
|
69
|
+
if ref_desc[0] != ":"
|
70
|
+
# [ data, ref_desc ]
|
71
|
+
reference_handle( data, ":#{ref_desc}" )
|
72
|
+
else
|
73
|
+
# Relative reference from root.
|
74
|
+
path = ref_desc.split( ":" )[1..-1]
|
75
|
+
scope = data
|
76
|
+
while path[0..-2].any?
|
77
|
+
if path[0] == "*"
|
78
|
+
# Wildcard for array.
|
79
|
+
unless path[1] && path[2]
|
80
|
+
raise XjsonReferenceError,
|
81
|
+
"Invalid reference: \"#{ref_desc}\" in \"#{@cur_file[0]}\", missing match key and value ..."
|
82
|
+
end
|
83
|
+
index = find_in_array_of_hash( scope, path[1], path[2] )
|
84
|
+
unless index
|
85
|
+
raise XjsonReferenceError,
|
86
|
+
"Invalid reference: \"#{ref_desc}\" in \"#{@cur_file[0]}\", key and value not matched ..."
|
87
|
+
end
|
88
|
+
scope = scope[ index ]
|
89
|
+
path.shift( 2 )
|
90
|
+
else
|
91
|
+
begin
|
92
|
+
index = Integer( path[0] )
|
93
|
+
scope = scope[ index ]
|
94
|
+
rescue
|
95
|
+
scope = scope[ path[0] ]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
path.shift
|
99
|
+
unless scope
|
100
|
+
raise XjsonReferenceError,
|
101
|
+
"Invalid reference: \"#{ref_desc}\" in \"#{@cur_file[0]}\"..."
|
102
|
+
end
|
103
|
+
end
|
104
|
+
[ scope, path[-1] ]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def reference( data, ref_desc )
|
109
|
+
path, label = reference_handle( data, ref_desc )
|
110
|
+
begin
|
111
|
+
index = Integer( label )
|
112
|
+
scope = path[ index ]
|
113
|
+
rescue
|
114
|
+
# scope = scope[ path[0] ]
|
115
|
+
scope = path[ label ]
|
116
|
+
end
|
117
|
+
# scope = path[ label ]
|
118
|
+
# if scope.class == String
|
119
|
+
scope
|
120
|
+
# else
|
121
|
+
# scope.to_s
|
122
|
+
# end
|
123
|
+
end
|
124
|
+
|
125
|
+
def override_desc( data, exp )
|
126
|
+
path, label = reference_handle( data, exp[0] )
|
127
|
+
{ path: path, label: label, value: exp[1] }
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
def override_apply( desc, overwrite = false )
|
132
|
+
if desc[:label] == "*"
|
133
|
+
desc[:path].each do |place|
|
134
|
+
if not( place[ desc[:value][0] ] ) || overwrite
|
135
|
+
place[ desc[:value][0] ] = desc[:value][1]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
else
|
139
|
+
if not( desc[:path][desc[:label]] ) || overwrite
|
140
|
+
desc[:path][desc[:label]] = desc[:value]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
def override( data, exp, overwrite = false )
|
147
|
+
desc = override_desc( data, exp )
|
148
|
+
override_apply( desc, overwrite )
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
# Expand json recursively.
|
153
|
+
def expand( data )
|
154
|
+
|
155
|
+
case data
|
156
|
+
|
157
|
+
when TrueClass; data
|
158
|
+
|
159
|
+
when FalseClass; data
|
160
|
+
|
161
|
+
when Float; data
|
162
|
+
|
163
|
+
when Integer; data
|
164
|
+
|
165
|
+
when String; data
|
166
|
+
|
167
|
+
when Array;
|
168
|
+
ret = []
|
169
|
+
@cur_data.unshift ret
|
170
|
+
data.each do |v|
|
171
|
+
value = expand( v )
|
172
|
+
ret.push( value ) if value
|
173
|
+
end
|
174
|
+
@cur_data.shift
|
175
|
+
ret
|
176
|
+
|
177
|
+
when Hash
|
178
|
+
|
179
|
+
if data.size == 1
|
180
|
+
|
181
|
+
# Most possible extension.
|
182
|
+
|
183
|
+
k, v = data.first
|
184
|
+
|
185
|
+
case k
|
186
|
+
|
187
|
+
when "@eval"
|
188
|
+
%x"#{expand(v)}".split("\n")
|
189
|
+
|
190
|
+
when "@env"
|
191
|
+
ENV[expand(v)]
|
192
|
+
|
193
|
+
when "@join"
|
194
|
+
flatten( v[1..-1].map{|i| expand( i )} ).join( v[0] )
|
195
|
+
|
196
|
+
when "@flat"
|
197
|
+
flatten( v[1..-1].map{|i| expand( i )} )
|
198
|
+
|
199
|
+
when "@self"
|
200
|
+
reference( @ext_data, expand(v) )
|
201
|
+
|
202
|
+
when "@over";
|
203
|
+
override( @cur_data[0], expand(v), true )
|
204
|
+
nil
|
205
|
+
|
206
|
+
when "@base";
|
207
|
+
override( @cur_data[0], expand(v), false )
|
208
|
+
nil
|
209
|
+
|
210
|
+
when "@null"
|
211
|
+
nil
|
212
|
+
|
213
|
+
when "@include";
|
214
|
+
jsonfile = expand(v)
|
215
|
+
subdata = read_json_file( jsonfile )
|
216
|
+
expdata = expand( subdata )
|
217
|
+
if expdata.class == Hash
|
218
|
+
if @cur_data[0].class == expdata.class
|
219
|
+
expdata.each do |ke,ve|
|
220
|
+
@cur_data[0][ ke ] = ve
|
221
|
+
end
|
222
|
+
else
|
223
|
+
raise XjsonIncludeError,
|
224
|
+
"Included file (\"#{jsonfile}\") must contain a hash as top level"
|
225
|
+
end
|
226
|
+
elsif expdata.class == Array
|
227
|
+
expdata.each do |ve|
|
228
|
+
@cur_data[0].push ve
|
229
|
+
end
|
230
|
+
else
|
231
|
+
raise XjsonIncludeError,
|
232
|
+
"Included file (\"#{jsonfile}\") must contain a hash or a an array as top level"
|
233
|
+
end
|
234
|
+
@cur_file.shift
|
235
|
+
nil
|
236
|
+
|
237
|
+
else
|
238
|
+
# Non-extension.
|
239
|
+
{ k => expand( v ) }
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
else
|
244
|
+
ret = {}
|
245
|
+
@cur_data.unshift ret
|
246
|
+
data.each do |k,v|
|
247
|
+
case k
|
248
|
+
when "@null"; nil
|
249
|
+
else
|
250
|
+
value = expand( v )
|
251
|
+
ret[ k ] = value if value
|
252
|
+
end
|
253
|
+
end
|
254
|
+
@cur_data.shift
|
255
|
+
ret
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def to_s
|
261
|
+
JSON.pretty_generate( @data )
|
262
|
+
end
|
263
|
+
|
264
|
+
def dump( filename )
|
265
|
+
File.write( filename, Marshal.dump( @data ) )
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
{
|
2
|
+
"action": "test",
|
3
|
+
"regressions": {
|
4
|
+
"all": {
|
5
|
+
"test": [
|
6
|
+
[
|
7
|
+
"t_run_1_2",
|
8
|
+
[
|
9
|
+
1234
|
10
|
+
]
|
11
|
+
],
|
12
|
+
[
|
13
|
+
"t_run_1_4",
|
14
|
+
[
|
15
|
+
1234
|
16
|
+
]
|
17
|
+
],
|
18
|
+
[
|
19
|
+
"t_run_2_1",
|
20
|
+
[
|
21
|
+
1234
|
22
|
+
]
|
23
|
+
],
|
24
|
+
[
|
25
|
+
"t_run_2_2",
|
26
|
+
[
|
27
|
+
1234
|
28
|
+
]
|
29
|
+
],
|
30
|
+
[
|
31
|
+
"t_run_7_1",
|
32
|
+
[
|
33
|
+
1234
|
34
|
+
]
|
35
|
+
],
|
36
|
+
{
|
37
|
+
"foobar1": "test1"
|
38
|
+
},
|
39
|
+
{
|
40
|
+
"foobar2": "test2"
|
41
|
+
}
|
42
|
+
]
|
43
|
+
}
|
44
|
+
},
|
45
|
+
"foobar1": "test1",
|
46
|
+
"foobar2": "test2",
|
47
|
+
"release": "201104",
|
48
|
+
"minor": "3",
|
49
|
+
"runroot": "prog-",
|
50
|
+
"home": "FOOBAR",
|
51
|
+
"dut_files": [
|
52
|
+
"/release/201104/src/main.c",
|
53
|
+
[
|
54
|
+
"YES: 3"
|
55
|
+
],
|
56
|
+
{
|
57
|
+
"myarr": [
|
58
|
+
"bar",
|
59
|
+
1,
|
60
|
+
2,
|
61
|
+
3
|
62
|
+
]
|
63
|
+
}
|
64
|
+
],
|
65
|
+
"eof": true
|
66
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
{
|
2
|
+
"action": "test",
|
3
|
+
|
4
|
+
"regressions": {
|
5
|
+
|
6
|
+
"all": {
|
7
|
+
"test": [
|
8
|
+
[ "t_run_1_2", [ 1234 ] ],
|
9
|
+
{ "@null": false },
|
10
|
+
[ "t_run_1_4", [ 1234 ] ],
|
11
|
+
[ "t_run_2_1", [ 1234 ] ],
|
12
|
+
[ "t_run_2_2", [ 1234 ] ],
|
13
|
+
[ "t_run_7_1", [ 1234 ] ],
|
14
|
+
{ "@include": "test/input/inc-arr.ext.json" }
|
15
|
+
]
|
16
|
+
}
|
17
|
+
},
|
18
|
+
|
19
|
+
"included-file": { "@include": "test/input/inc-hash.ext.json" },
|
20
|
+
|
21
|
+
"release" : "201104",
|
22
|
+
"minor" : "3",
|
23
|
+
"runroot" : { "@join": [ "-", "prog", {"@self":":regressions:all:test:1:0"} ] },
|
24
|
+
"home" : { "@env": "XJSON_FOOBAR" },
|
25
|
+
|
26
|
+
|
27
|
+
"dut_files": [
|
28
|
+
{ "@join": [ "/", "/release", {"@self":"release"}, "src/main.c" ] },
|
29
|
+
{ "@eval": { "@join": [ " ", "echo YES:", {"@self": "minor"} ] } },
|
30
|
+
{ "myarr": { "@flat" : [ "foo", "bar", [ 1, 2 ,3 ] ] } }
|
31
|
+
],
|
32
|
+
|
33
|
+
"eof": true
|
34
|
+
}
|
data/test/test_xjson.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/xjson.rb'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class XjsonTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_basic
|
8
|
+
|
9
|
+
FileUtils.mkdir_p( "test/result" )
|
10
|
+
|
11
|
+
ENV['XJSON_FOOBAR'] = "FOOBAR"
|
12
|
+
|
13
|
+
ifile = 'test/input/test.ext.json'
|
14
|
+
|
15
|
+
# Open file.
|
16
|
+
json = Xjson.new( ifile )
|
17
|
+
ofile = "test/result/test.json"
|
18
|
+
File.write( ofile, JSON.pretty_generate( json.data ) )
|
19
|
+
|
20
|
+
golden_data = File.read( "test/golden/test.json" )
|
21
|
+
design_data = File.read( ofile )
|
22
|
+
|
23
|
+
assert_equal( golden_data, design_data )
|
24
|
+
|
25
|
+
FileUtils.rm_f ofile
|
26
|
+
FileUtils.rm_f "test/result"
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
#require_relative '../lib/xjson.rb'
|
33
|
+
#require 'fileutils'
|
34
|
+
#FileUtils.mkdir_p( "test/result" )
|
35
|
+
#
|
36
|
+
#ifile = 'test/input/test.ext.json'
|
37
|
+
#
|
38
|
+
## Open file.
|
39
|
+
#json = Xjson.new( ifile )
|
40
|
+
#ofile = "test/result/test.json"
|
41
|
+
#File.write( ofile, JSON.pretty_generate( json.data ) )
|
42
|
+
#
|
43
|
+
#golden_data = File.read( "test/golden/test.json" )
|
44
|
+
#design_data = File.read( ofile )
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xjson
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tero Isannainen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-07-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Xjson is extension to JSON format.
|
14
|
+
email: tero.isannainen@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files:
|
18
|
+
- README.rdoc
|
19
|
+
- CHANGELOG.rdoc
|
20
|
+
files:
|
21
|
+
- CHANGELOG.rdoc
|
22
|
+
- LICENSE
|
23
|
+
- README.rdoc
|
24
|
+
- doc/Xjson.html
|
25
|
+
- doc/Xjson/XjsonIncludeError.html
|
26
|
+
- doc/Xjson/XjsonReferenceError.html
|
27
|
+
- doc/_index.html
|
28
|
+
- doc/class_list.html
|
29
|
+
- doc/css/common.css
|
30
|
+
- doc/css/full_list.css
|
31
|
+
- doc/css/style.css
|
32
|
+
- doc/file.CHANGELOG.html
|
33
|
+
- doc/file.README.html
|
34
|
+
- doc/file_list.html
|
35
|
+
- doc/frames.html
|
36
|
+
- doc/index.html
|
37
|
+
- doc/js/app.js
|
38
|
+
- doc/js/full_list.js
|
39
|
+
- doc/js/jquery.js
|
40
|
+
- doc/method_list.html
|
41
|
+
- doc/top-level-namespace.html
|
42
|
+
- lib/xjson.rb
|
43
|
+
- test/golden/test.json
|
44
|
+
- test/input/inc-arr.ext.json
|
45
|
+
- test/input/inc-hash.ext.json
|
46
|
+
- test/input/test.ext.json
|
47
|
+
- test/test_xjson.rb
|
48
|
+
homepage:
|
49
|
+
licenses:
|
50
|
+
- Ruby
|
51
|
+
metadata: {}
|
52
|
+
post_install_message: Check README...
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.9.3
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubygems_version: 3.2.5
|
68
|
+
signing_key:
|
69
|
+
specification_version: 4
|
70
|
+
summary: Xjson is extension to JSON format.
|
71
|
+
test_files: []
|