json-next 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +9 -0
- data/README.md +139 -10
- data/Rakefile +1 -1
- data/lib/json/next.rb +1 -0
- data/lib/json/next/commata.rb +1 -1
- data/lib/json/next/parser/jsonx.rb +108 -0
- data/lib/json/next/version.rb +1 -1
- data/test/data/commata1.txt +19 -0
- data/test/data/commata2a.txt +23 -0
- data/test/data/commata2b.txt +22 -0
- data/test/data/hanson1.txt +31 -0
- data/test/data/jsonx1.txt +34 -0
- data/test/data/jsonx2.txt +31 -0
- data/test/data/son1.txt +21 -0
- data/test/helper.rb +30 -0
- data/test/test_commata.rb +21 -75
- data/test/test_parser_hanson.rb +3 -31
- data/test/test_parser_jsonx.rb +29 -0
- data/test/test_parser_son.rb +3 -22
- metadata +14 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8be12b2735cd395e2b7df815212ae0883813ebd5
|
4
|
+
data.tar.gz: c2825771ae3b950e828fdc3de35261b039bec33c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e70939b56c4c28d44ac85ee00e3b8c03d0e835ed408f47aef1a5e521a6eb92f76f7ad35bbad3b1e3a8873da903a04f38b095822ea25f7a5896d2899f4ba767f
|
7
|
+
data.tar.gz: 3c45fdada52846cc88eccad43f6bab60ed63e7ef59a6f9ec352fa61995c914d05405174ccc357d4af4c90e80d11ed74b3d2c77c5179ccd5bfc51407b05420145
|
data/Manifest.txt
CHANGED
@@ -5,11 +5,20 @@ Rakefile
|
|
5
5
|
lib/json/next.rb
|
6
6
|
lib/json/next/commata.rb
|
7
7
|
lib/json/next/parser/hanson.rb
|
8
|
+
lib/json/next/parser/jsonx.rb
|
8
9
|
lib/json/next/parser/son.rb
|
9
10
|
lib/json/next/pattern.rb
|
10
11
|
lib/json/next/version.rb
|
12
|
+
test/data/commata1.txt
|
13
|
+
test/data/commata2a.txt
|
14
|
+
test/data/commata2b.txt
|
15
|
+
test/data/hanson1.txt
|
16
|
+
test/data/jsonx1.txt
|
17
|
+
test/data/jsonx2.txt
|
18
|
+
test/data/son1.txt
|
11
19
|
test/helper.rb
|
12
20
|
test/test_commata.rb
|
13
21
|
test/test_parser_hanson.rb
|
22
|
+
test/test_parser_jsonx.rb
|
14
23
|
test/test_parser_son.rb
|
15
24
|
test/test_version.rb
|
data/README.md
CHANGED
@@ -1,20 +1,21 @@
|
|
1
|
-
#
|
1
|
+
# json-next
|
2
2
|
|
3
|
-
|
3
|
+
json-next gem - read generation y / next generation json versions (HanSON, SON, JSONX/JSON11, etc.) with comments, unquoted keys, multi-line strings, trailing commas, optional commas, and more
|
4
4
|
|
5
5
|
|
6
|
-
* home :: [github.com/datatxt/
|
7
|
-
* bugs :: [github.com/datatxt/
|
8
|
-
* gem :: [rubygems.org/gems/
|
9
|
-
* rdoc :: [rubydoc.info/gems/
|
6
|
+
* home :: [github.com/datatxt/json-next](https://github.com/datatxt/json-next)
|
7
|
+
* bugs :: [github.com/datatxt/json-next/issues](https://github.com/datatxt/json-next/issues)
|
8
|
+
* gem :: [rubygems.org/gems/json-next](https://rubygems.org/gems/json-next)
|
9
|
+
* rdoc :: [rubydoc.info/gems/json-next](http://rubydoc.info/gems/json-next)
|
10
10
|
|
11
11
|
|
12
12
|
|
13
13
|
|
14
|
-
## Usage - `HANSON.parse`, `SON.parse`
|
14
|
+
## Usage - `HANSON.parse`, `SON.parse`, `JSONX.parse`
|
15
15
|
|
16
16
|
[HanSON](#hanson) •
|
17
|
-
[SON](#son)
|
17
|
+
[SON](#son) •
|
18
|
+
[JSONX](#jsonx)
|
18
19
|
|
19
20
|
|
20
21
|
### HanSON
|
@@ -153,12 +154,93 @@ Use `SON.parse` instead of `JSON.parse` to parse text to ruby hash / array / etc
|
|
153
154
|
```
|
154
155
|
|
155
156
|
|
157
|
+
### JSONX
|
158
|
+
|
159
|
+
_JSON with Extensions or JSON v1.1 (a.k.a. JSON11 or JSON XI or JSON II)_
|
160
|
+
|
161
|
+
Includes all JSON extensions from HanSON:
|
162
|
+
|
163
|
+
- quotes for strings are optional if they follow JavaScript identifier rules.
|
164
|
+
- you can alternatively use backticks, as in ES6's template string literal, as quotes for strings.
|
165
|
+
A backtick-quoted string may span several lines and you are not required to escape regular quote characters,
|
166
|
+
only backticks. Backslashes still need to be escaped, and all other backslash-escape sequences work like in
|
167
|
+
regular JSON.
|
168
|
+
- for single-line strings, single quotes (`''`) are supported in addition to double quotes (`""`)
|
169
|
+
- you can use JavaScript comments, both single line (`//`) and multi-line comments (`/* */`), in all places where JSON allows whitespace.
|
170
|
+
- Commas after the last list element or object property will be ignored.
|
171
|
+
|
172
|
+
Plus all JSON extensions from SON:
|
173
|
+
|
174
|
+
- comments starts with `#` sign and ends with newline (`\n`)
|
175
|
+
- comma after an object key-value pair is optional
|
176
|
+
- comma after an array item is optional
|
177
|
+
|
178
|
+
|
179
|
+
Example:
|
180
|
+
|
181
|
+
```
|
182
|
+
{
|
183
|
+
# use shell-like (or ruby-like) comments
|
184
|
+
|
185
|
+
listName: "Sesame Street Monsters" # note: comments after key-value pairs are optional
|
186
|
+
content: [
|
187
|
+
{
|
188
|
+
name: "Cookie Monster"
|
189
|
+
// note: the template quotes and unescaped regular quotes in the next string
|
190
|
+
background: `Cookie Monster used to be a
|
191
|
+
monster that ate everything, especially cookies.
|
192
|
+
These days he is forced to eat "healthy" food.`
|
193
|
+
}, {
|
194
|
+
// You can single-quote strings too:
|
195
|
+
name: 'Herry Monster',
|
196
|
+
background: `Herry Monster is a furry blue monster with a purple nose.
|
197
|
+
He's mostly retired today.`
|
198
|
+
}, /* don't worry, the trailing comma will be ignored */
|
199
|
+
]
|
200
|
+
}
|
201
|
+
```
|
202
|
+
|
203
|
+
|
204
|
+
Use `JSONX.convert` (or `JSONXI.convert` or `JSON11.convert` or `JSONII.convert`) to convert JSONX text to ye old' JSON text:
|
205
|
+
|
206
|
+
|
207
|
+
``` json
|
208
|
+
{
|
209
|
+
"listName": "Sesame Street Monsters",
|
210
|
+
"content": [
|
211
|
+
{ "name": "Cookie Monster",
|
212
|
+
"background": "Cookie Monster used to be a\n ... to eat \"healthy\" food."
|
213
|
+
},
|
214
|
+
{ "name": "Herry Monster",
|
215
|
+
"background": "Herry Monster is a furry blue monster with a purple nose.\n ... today."
|
216
|
+
}
|
217
|
+
]
|
218
|
+
}
|
219
|
+
```
|
220
|
+
|
221
|
+
Use `JSONX.parse` (or `JSONXI.parse` or `JSON11.parse` or `JSONII.parse`) instead of `JSON.parse` to parse text to ruby hash / array / etc.:
|
222
|
+
|
223
|
+
``` ruby
|
224
|
+
{
|
225
|
+
"listName" => "Sesame Street Monsters",
|
226
|
+
"content" => [
|
227
|
+
{ "name" => "Cookie Monster",
|
228
|
+
"background" => "Cookie Monster used to be a\n ... to eat \"healthy\" food."
|
229
|
+
},
|
230
|
+
{ "name" => "Herry Monster",
|
231
|
+
"background" => "Herry Monster is a furry blue monster with a purple nose.\n ... today."
|
232
|
+
}
|
233
|
+
]
|
234
|
+
}
|
235
|
+
```
|
236
|
+
|
237
|
+
|
156
238
|
|
157
239
|
### Live Examples
|
158
240
|
|
159
241
|
|
160
242
|
``` ruby
|
161
|
-
require '
|
243
|
+
require 'json/next'
|
162
244
|
|
163
245
|
text1 =<<TXT
|
164
246
|
{
|
@@ -236,6 +318,53 @@ resulting in:
|
|
236
318
|
}
|
237
319
|
```
|
238
320
|
|
321
|
+
and
|
322
|
+
|
323
|
+
``` ruby
|
324
|
+
text3 =<<TXT
|
325
|
+
{
|
326
|
+
# use shell-like (or ruby-like) comments
|
327
|
+
|
328
|
+
listName: "Sesame Street Monsters" # note: comments after key-value pairs are optional
|
329
|
+
content: [
|
330
|
+
{
|
331
|
+
name: "Cookie Monster"
|
332
|
+
// note: the template quotes and unescaped regular quotes in the next string
|
333
|
+
background: `Cookie Monster used to be a
|
334
|
+
monster that ate everything, especially cookies.
|
335
|
+
These days he is forced to eat "healthy" food.`
|
336
|
+
}, {
|
337
|
+
// You can single-quote strings too:
|
338
|
+
name: 'Herry Monster',
|
339
|
+
background: `Herry Monster is a furry blue monster with a purple nose.
|
340
|
+
He's mostly retired today.`
|
341
|
+
}, /* don't worry, the trailing comma will be ignored */
|
342
|
+
]
|
343
|
+
}
|
344
|
+
TXT
|
345
|
+
|
346
|
+
pp JSONX.parse( text3 ) # note: is the same as JSON.parse( JSONX.convert( text ))
|
347
|
+
pp JSONXI.parse( text3 ) # note: is the same as JSON.parse( JSONXI.convert( text ))
|
348
|
+
pp JSON11.parse( text3 ) # note: is the same as JSON.parse( JSON11.convert( text ))
|
349
|
+
pp JSONII.parse( text3 ) # note: is the same as JSON.parse( JSONII.convert( text ))
|
350
|
+
```
|
351
|
+
|
352
|
+
resulting in:
|
353
|
+
|
354
|
+
``` ruby
|
355
|
+
{
|
356
|
+
"listName" => "Sesame Street Monsters",
|
357
|
+
"content" => [
|
358
|
+
{ "name" => "Cookie Monster",
|
359
|
+
"background" => "Cookie Monster used to be a\n ... to eat \"healthy\" food."
|
360
|
+
},
|
361
|
+
{ "name" => "Herry Monster",
|
362
|
+
"background" => "Herry Monster is a furry blue monster with a purple nose.\n ... today."
|
363
|
+
}
|
364
|
+
]
|
365
|
+
}
|
366
|
+
```
|
367
|
+
|
239
368
|
|
240
369
|
|
241
370
|
## More JSON Formats
|
@@ -248,7 +377,7 @@ See the [Awesome JSON (What's Next?)](https://github.com/datatxt/awesome-json-ne
|
|
248
377
|
|
249
378
|
![](https://publicdomainworks.github.io/buttons/zero88x31.png)
|
250
379
|
|
251
|
-
The `
|
380
|
+
The `json-next` scripts are dedicated to the public domain.
|
252
381
|
Use it as you please with no restrictions whatsoever.
|
253
382
|
|
254
383
|
## Questions? Comments?
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ Hoe.spec 'json-next' do
|
|
5
5
|
|
6
6
|
self.version = JSON::Next::VERSION
|
7
7
|
|
8
|
-
self.summary = 'json-next - read generation y / next generation json versions (HanSON, SON, etc.) with comments, unquoted keys, multi-line strings, trailing commas, optional commas, and more'
|
8
|
+
self.summary = 'json-next - read generation y / next generation json versions (HanSON, SON, JSONX/JSON11, etc.) with comments, unquoted keys, multi-line strings, trailing commas, optional commas, and more'
|
9
9
|
self.description = summary
|
10
10
|
|
11
11
|
self.urls = ['https://github.com/datatxt/json-next']
|
data/lib/json/next.rb
CHANGED
data/lib/json/next/commata.rb
CHANGED
@@ -38,7 +38,7 @@ def parse_string
|
|
38
38
|
|
39
39
|
if @buffer.peek(1) == '"' ## double quote
|
40
40
|
@buffer.getch # consume double quote
|
41
|
-
value = @buffer.
|
41
|
+
value = @buffer.scan( /(\\.|[^"])*/ )
|
42
42
|
@buffer.getch # consume double quote
|
43
43
|
|
44
44
|
puts %{string value >>#{value}<<} if debug?
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
##
|
5
|
+
## JSON with Extensions (JSONX) or
|
6
|
+
## JSON 1.1 - JSON XI
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
module JSONX
|
11
|
+
|
12
|
+
|
13
|
+
BACKTICK_ML_QUOTE = JSON::Next::BACKTICK_ML_QUOTE
|
14
|
+
SINGLE_QUOTE = JSON::Next::SINGLE_QUOTE
|
15
|
+
DOUBLE_QUOTE = JSON::Next::DOUBLE_QUOTE
|
16
|
+
|
17
|
+
CLANG_ML_COMMENT = JSON::Next::CLANG_ML_COMMENT
|
18
|
+
CLANG_COMMENT = JSON::Next::CLANG_COMMENT
|
19
|
+
SHELL_COMMENT = JSON::Next::SHELL_COMMENT
|
20
|
+
|
21
|
+
KEYWORDS = JSON::Next::KEYWORDS
|
22
|
+
IDENTIFIER = JSON::Next::IDENTIFIER
|
23
|
+
TRAILING_COMMA = JSON::Next::TRAILING_COMMA
|
24
|
+
|
25
|
+
UNESCAPE_MAP = JSON::Next::UNESCAPE_MAP
|
26
|
+
ML_ESCAPE_MAP = JSON::Next::ML_ESCAPE_MAP
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
def self.strip_comments( text ) ## pass 1
|
31
|
+
text.gsub( /#{BACKTICK_ML_QUOTE}|#{SINGLE_QUOTE}|#{DOUBLE_QUOTE}|#{SHELL_COMMENT}|#{CLANG_ML_COMMENT}|#{CLANG_COMMENT}/ox ) do |match|
|
32
|
+
## puts "match: >>#{match}<< : #{match.class.name}"
|
33
|
+
if match[0] == ?/ || match[0] == ?# ## comments start with // or /* or #
|
34
|
+
## puts "!!! removing comments"
|
35
|
+
'' ## remove / strip comments
|
36
|
+
else
|
37
|
+
match
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
### note: same as hanson (see parser/hanson.rb)
|
44
|
+
def self.normalize_quotes( text ) ## pass 2
|
45
|
+
text.gsub( /#{BACKTICK_ML_QUOTE}|#{SINGLE_QUOTE}|#{DOUBLE_QUOTE}/ox ) do |match|
|
46
|
+
## puts "match: >>#{match}<< : #{match.class.name}"
|
47
|
+
|
48
|
+
m = Regexp.last_match
|
49
|
+
if m[:backtick_ml_quote]
|
50
|
+
## puts "!!! ml_quote -- convert to double quotes"
|
51
|
+
str = m[:backtick_ml_quote]
|
52
|
+
str = str.gsub( /\\./ ) {|r| UNESCAPE_MAP[r] || r }
|
53
|
+
str = str.gsub( /[\n\r\t"]/ ) { |r| ML_ESCAPE_MAP[r] }
|
54
|
+
'"' + str + '"'
|
55
|
+
elsif m[:single_quote]
|
56
|
+
## puts "!!! single_quote -- convert to double quotes"
|
57
|
+
str = m[:single_quote]
|
58
|
+
str = str.gsub( /\\./ ) {|r| UNESCAPE_MAP[r] || r }
|
59
|
+
str = str.gsub( /"/, %{\\"} )
|
60
|
+
'"' + str + '"'
|
61
|
+
else
|
62
|
+
match
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def self.convert( text )
|
69
|
+
|
70
|
+
## pass 1: remove/strip comments
|
71
|
+
text = strip_comments( text )
|
72
|
+
|
73
|
+
## pass 2: requote/normalize quotes
|
74
|
+
text = normalize_quotes( text )
|
75
|
+
|
76
|
+
## pass 3: quote unquoted and remove trailing commas
|
77
|
+
text = text.gsub( /#{KEYWORDS}|#{IDENTIFIER}|#{DOUBLE_QUOTE}|#{TRAILING_COMMA}/ox ) do |match|
|
78
|
+
## puts "match: >>#{match}<< : #{match.class.name}"
|
79
|
+
|
80
|
+
m = Regexp.last_match
|
81
|
+
if m[:identifier]
|
82
|
+
## puts "!!! identfier -- wrap in double quotes"
|
83
|
+
'"' + m[:identifier] + '"'
|
84
|
+
elsif m[:trailing_comma]
|
85
|
+
## puts "!!! trailing comma -- remove"
|
86
|
+
''
|
87
|
+
else
|
88
|
+
match
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
## pass 4 - auto-add (missing optional) commas
|
93
|
+
text = JSON::Next::Commata.convert( text )
|
94
|
+
text
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def self.parse( text )
|
99
|
+
JSON.parse( self.convert( text ) )
|
100
|
+
end
|
101
|
+
|
102
|
+
end # module JSONX
|
103
|
+
|
104
|
+
## add some aliases
|
105
|
+
|
106
|
+
JSONXI = JSONX
|
107
|
+
JSONII = JSONX
|
108
|
+
JSON11 = JSONX
|
data/lib/json/next/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"name": "Alexander Grothendieck"
|
3
|
+
"fields": "mathematics"
|
4
|
+
"main_topics": [
|
5
|
+
"Etale cohomology"
|
6
|
+
"Motives"
|
7
|
+
"Topos theory"
|
8
|
+
"Schemes"
|
9
|
+
]
|
10
|
+
}
|
11
|
+
|
12
|
+
---
|
13
|
+
|
14
|
+
{
|
15
|
+
"name" => "Alexander Grothendieck",
|
16
|
+
"fields" => "mathematics",
|
17
|
+
"main_topics" =>
|
18
|
+
["Etale cohomology", "Motives", "Topos theory", "Schemes"]
|
19
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
{
|
2
|
+
"nested": {
|
3
|
+
"name": "Alexander Grothendieck"
|
4
|
+
"fields": "mathematics"
|
5
|
+
"array": ["one" "two"] }
|
6
|
+
"numbers": [1 2 3 4 5]
|
7
|
+
"more_numbers": [1.1 2.0 0.3 4.444 -5.1]
|
8
|
+
"mixed": [1 true false null]
|
9
|
+
}
|
10
|
+
|
11
|
+
|
12
|
+
---
|
13
|
+
|
14
|
+
{
|
15
|
+
"nested" => {
|
16
|
+
"name" => "Alexander Grothendieck",
|
17
|
+
"fields" => "mathematics",
|
18
|
+
"array" => ["one", "two"]
|
19
|
+
},
|
20
|
+
"numbers" => [1, 2, 3, 4, 5],
|
21
|
+
"more_numbers" => [1.1, 2.0, 0.3, 4.444, -5.1],
|
22
|
+
"mixed" => [1, true, false, nil]
|
23
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"nested": {
|
3
|
+
"name": "Alexander Grothendieck",
|
4
|
+
"fields": "mathematics",
|
5
|
+
"array": ["one", "two"] },
|
6
|
+
"numbers": [1, 2, 3, 4, 5],
|
7
|
+
"more_numbers": [1.1, 2.0, 0.3, 4.444, -5.1],
|
8
|
+
"mixed": [1, true, false, null]
|
9
|
+
}
|
10
|
+
|
11
|
+
---
|
12
|
+
|
13
|
+
{
|
14
|
+
"nested" => {
|
15
|
+
"name" => "Alexander Grothendieck",
|
16
|
+
"fields" => "mathematics",
|
17
|
+
"array" => ["one", "two"]
|
18
|
+
},
|
19
|
+
"numbers" => [1, 2, 3, 4, 5],
|
20
|
+
"more_numbers" => [1.1, 2.0, 0.3, 4.444, -5.1],
|
21
|
+
"mixed" => [1, true, false, nil]
|
22
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
{
|
2
|
+
listName: "Sesame Street Monsters", // note that listName needs no quotes
|
3
|
+
content: [
|
4
|
+
{
|
5
|
+
name: "Cookie Monster",
|
6
|
+
/* Note the template quotes and unescaped regular quotes in the next string */
|
7
|
+
background: `Cookie Monster used to be a
|
8
|
+
monster that ate everything, especially cookies.
|
9
|
+
These days he is forced to eat "healthy" food.`
|
10
|
+
}, {
|
11
|
+
// You can single-quote strings too:
|
12
|
+
name: 'Herry Monster',
|
13
|
+
background: `Herry Monster is a furry blue monster with a purple nose.
|
14
|
+
He's mostly retired today.`
|
15
|
+
}, // don't worry, the trailing comma will be ignored
|
16
|
+
]
|
17
|
+
}
|
18
|
+
|
19
|
+
---
|
20
|
+
|
21
|
+
{
|
22
|
+
"listName" => "Sesame Street Monsters",
|
23
|
+
"content" =>
|
24
|
+
[{"name" => "Cookie Monster",
|
25
|
+
"background" =>
|
26
|
+
"Cookie Monster used to be a\nmonster that ate everything, especially cookies.\nThese days he is forced to eat \"healthy\" food."},
|
27
|
+
{"name" => "Herry Monster",
|
28
|
+
"background" =>
|
29
|
+
"Herry Monster is a furry blue monster with a purple nose.\nHe's mostly retired today."}
|
30
|
+
]
|
31
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
{
|
2
|
+
# use shell-like comments
|
3
|
+
# note: all commas optional
|
4
|
+
|
5
|
+
listName: "Sesame Street Monsters" // note that listName needs no quotes
|
6
|
+
content: [
|
7
|
+
{
|
8
|
+
name: "Cookie Monster"
|
9
|
+
/* Note the template quotes and unescaped regular quotes in the next string */
|
10
|
+
background: `Cookie Monster used to be a
|
11
|
+
monster that ate everything, especially cookies.
|
12
|
+
These days he is forced to eat "healthy" food.`
|
13
|
+
} {
|
14
|
+
// You can single-quote strings too:
|
15
|
+
name: 'Herry Monster'
|
16
|
+
background: `Herry Monster is a furry blue monster with a purple nose.
|
17
|
+
He's mostly retired today.`
|
18
|
+
}
|
19
|
+
]
|
20
|
+
}
|
21
|
+
|
22
|
+
---
|
23
|
+
|
24
|
+
{
|
25
|
+
"listName" => "Sesame Street Monsters",
|
26
|
+
"content" =>
|
27
|
+
[{"name" => "Cookie Monster",
|
28
|
+
"background" =>
|
29
|
+
"Cookie Monster used to be a\nmonster that ate everything, especially cookies.\nThese days he is forced to eat \"healthy\" food."},
|
30
|
+
{"name" => "Herry Monster",
|
31
|
+
"background" =>
|
32
|
+
"Herry Monster is a furry blue monster with a purple nose.\nHe's mostly retired today."}
|
33
|
+
]
|
34
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
{
|
2
|
+
listName: "Sesame Street Monsters" # note that listName needs no quotes
|
3
|
+
content: [
|
4
|
+
{
|
5
|
+
name: "Cookie Monster"
|
6
|
+
/* Note the template quotes and unescaped regular quotes in the next string */
|
7
|
+
background: `Cookie Monster used to be a
|
8
|
+
monster that ate everything, especially cookies.
|
9
|
+
These days he is forced to eat "healthy" food.`
|
10
|
+
}, {
|
11
|
+
# You can single-quote strings too:
|
12
|
+
name: 'Herry Monster',
|
13
|
+
background: `Herry Monster is a furry blue monster with a purple nose.
|
14
|
+
He's mostly retired today.`
|
15
|
+
}, /* don't worry, the trailing comma will be ignored */
|
16
|
+
]
|
17
|
+
}
|
18
|
+
|
19
|
+
---
|
20
|
+
|
21
|
+
{
|
22
|
+
"listName" => "Sesame Street Monsters",
|
23
|
+
"content" =>
|
24
|
+
[{"name" => "Cookie Monster",
|
25
|
+
"background" =>
|
26
|
+
"Cookie Monster used to be a\nmonster that ate everything, especially cookies.\nThese days he is forced to eat \"healthy\" food."},
|
27
|
+
{"name" => "Herry Monster",
|
28
|
+
"background" =>
|
29
|
+
"Herry Monster is a furry blue monster with a purple nose.\nHe's mostly retired today."}
|
30
|
+
]
|
31
|
+
}
|
data/test/data/son1.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
# Personal information
|
3
|
+
|
4
|
+
"name": "Alexander Grothendieck"
|
5
|
+
"fields": "mathematics"
|
6
|
+
"main_topics": [
|
7
|
+
"Etale cohomology"
|
8
|
+
"Motives"
|
9
|
+
"Topos theory"
|
10
|
+
"Schemes"
|
11
|
+
]
|
12
|
+
}
|
13
|
+
|
14
|
+
---
|
15
|
+
|
16
|
+
{
|
17
|
+
"name" => "Alexander Grothendieck",
|
18
|
+
"fields" => "mathematics",
|
19
|
+
"main_topics" =>
|
20
|
+
["Etale cohomology", "Motives", "Topos theory", "Schemes"]
|
21
|
+
}
|
data/test/helper.rb
CHANGED
@@ -8,3 +8,33 @@ $RUBYLIBS_DEBUG = true
|
|
8
8
|
|
9
9
|
## our own code
|
10
10
|
require 'json/next'
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
class TestBlockFile
|
16
|
+
def self.read_utf8( path )
|
17
|
+
BlockFile.read_utf8( "#{JSON::Next.root}/test/data/#{path}.txt" )
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
class BlockFile
|
23
|
+
def self.read_utf8( path )
|
24
|
+
text = File.open( path, 'r:bom|utf-8' ).read
|
25
|
+
reader = BlockReader.new( text )
|
26
|
+
reader.blocks
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
class BlockReader
|
32
|
+
|
33
|
+
attr_reader :blocks
|
34
|
+
|
35
|
+
def initialize( text )
|
36
|
+
## split blocks by ---
|
37
|
+
@blocks = text.split( /^\s*---\s*$/ )
|
38
|
+
end
|
39
|
+
|
40
|
+
end ## block reader
|
data/test/test_commata.rb
CHANGED
@@ -12,81 +12,27 @@ class TestCommata < MiniTest::Test
|
|
12
12
|
|
13
13
|
def test_commata
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
sample2a =<<TXT
|
37
|
-
{
|
38
|
-
"nested": {
|
39
|
-
"name": "Alexander Grothendieck"
|
40
|
-
"fields": "mathematics"
|
41
|
-
"array": ["one" "two"] }
|
42
|
-
"numbers": [1 2 3 4 5]
|
43
|
-
"more_numbers": [1.1 2.0 0.3 4.444 -5.1]
|
44
|
-
"mixed": [1 true false null]
|
45
|
-
}
|
46
|
-
TXT
|
47
|
-
|
48
|
-
sample2a1 =<<TXT
|
49
|
-
{
|
50
|
-
"nested": {
|
51
|
-
"name": "Alexander Grothendieck",
|
52
|
-
"fields": "mathematics",
|
53
|
-
"array": ["one", "two"] },
|
54
|
-
"numbers": [1, 2, 3, 4, 5],
|
55
|
-
"more_numbers": [1.1, 2.0, 0.3, 4.444, -5.1],
|
56
|
-
"mixed": [1, true, false, null]
|
57
|
-
}
|
58
|
-
TXT
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
exp_sample2b = {
|
63
|
-
"nested" => {
|
64
|
-
"name" => "Alexander Grothendieck",
|
65
|
-
"fields" => "mathematics",
|
66
|
-
"array" => ["one", "two"]
|
67
|
-
},
|
68
|
-
"numbers" => [1, 2, 3, 4, 5],
|
69
|
-
"more_numbers" => [1.1, 2.0, 0.3, 4.444, -5.1],
|
70
|
-
"mixed" => [1, true, false, nil]
|
71
|
-
}
|
72
|
-
|
73
|
-
|
74
|
-
sample1b = JSON::Next::Commata.convert( sample1a, debug: true )
|
75
|
-
puts sample1b
|
76
|
-
|
77
|
-
assert_equal exp_sample1b, JSON.parse( sample1b )
|
78
|
-
|
79
|
-
|
80
|
-
sample2b = JSON::Next::Commata.convert( sample2a, debug: true )
|
81
|
-
puts sample2b
|
82
|
-
|
83
|
-
assert_equal exp_sample2b, JSON.parse( sample2b )
|
84
|
-
|
85
|
-
|
86
|
-
sample2b1 = JSON::Next::Commata.convert( sample2a1, debug: true )
|
87
|
-
puts sample2b1
|
88
|
-
|
89
|
-
assert_equal exp_sample2b, JSON.parse( sample2b1 )
|
15
|
+
|
16
|
+
sample1, exp1 = TestBlockFile.read_utf8( 'commata1' )
|
17
|
+
sample2a, exp2a = TestBlockFile.read_utf8( 'commata2a' )
|
18
|
+
sample2b, exp2b = TestBlockFile.read_utf8( 'commata2b' )
|
19
|
+
|
20
|
+
json1 = JSON::Next::Commata.convert( sample1, debug: true )
|
21
|
+
puts json1
|
22
|
+
|
23
|
+
assert_equal eval(exp1), JSON.parse( json1 )
|
24
|
+
|
25
|
+
|
26
|
+
json2a = JSON::Next::Commata.convert( sample2a, debug: true )
|
27
|
+
puts json2a
|
28
|
+
|
29
|
+
assert_equal eval(exp2a), JSON.parse( json2a )
|
30
|
+
|
31
|
+
|
32
|
+
json2b = JSON::Next::Commata.convert( sample2b, debug: true )
|
33
|
+
puts json2b
|
34
|
+
|
35
|
+
assert_equal eval(exp2b), JSON.parse( json2b )
|
90
36
|
end
|
91
37
|
|
92
38
|
end
|
data/test/test_parser_hanson.rb
CHANGED
@@ -11,42 +11,14 @@ require 'helper'
|
|
11
11
|
class TestParser < MiniTest::Test
|
12
12
|
|
13
13
|
def test_hanson
|
14
|
-
|
15
|
-
|
16
|
-
"content"=>
|
17
|
-
[{"name"=>"Cookie Monster",
|
18
|
-
"background"=> "Cookie Monster used to be a\n monster that ate everything, especially cookies.\n These days he is forced to eat \"healthy\" food."
|
19
|
-
},
|
20
|
-
{"name"=>"Herry Monster",
|
21
|
-
"background"=> "Herry Monster is a furry blue monster with a purple nose.\n He's mostly retired today."
|
22
|
-
}
|
23
|
-
]}
|
24
|
-
|
25
|
-
sample1 =<<TXT
|
26
|
-
{
|
27
|
-
listName: "Sesame Street Monsters", // note that listName needs no quotes
|
28
|
-
content: [
|
29
|
-
{
|
30
|
-
name: "Cookie Monster",
|
31
|
-
/* Note the template quotes and unescaped regular quotes in the next string */
|
32
|
-
background: `Cookie Monster used to be a
|
33
|
-
monster that ate everything, especially cookies.
|
34
|
-
These days he is forced to eat "healthy" food.`
|
35
|
-
}, {
|
36
|
-
// You can single-quote strings too:
|
37
|
-
name: 'Herry Monster',
|
38
|
-
background: `Herry Monster is a furry blue monster with a purple nose.
|
39
|
-
He's mostly retired today.`
|
40
|
-
}, // don't worry, the trailing comma will be ignored
|
41
|
-
]
|
42
|
-
}
|
43
|
-
TXT
|
14
|
+
|
15
|
+
sample1, exp1 = TestBlockFile.read_utf8( 'hanson1' )
|
44
16
|
|
45
17
|
puts HANSON.convert( sample1 )
|
46
18
|
|
47
19
|
pp HANSON.parse( sample1 )
|
48
20
|
|
49
|
-
assert_equal
|
21
|
+
assert_equal eval( exp1 ), HANSON.parse( sample1 )
|
50
22
|
end
|
51
23
|
|
52
24
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
###
|
4
|
+
# to run use
|
5
|
+
# ruby -I ./lib -I ./test test/test_parser_jsonx.rb
|
6
|
+
|
7
|
+
|
8
|
+
require 'helper'
|
9
|
+
|
10
|
+
|
11
|
+
class TestParserJsonx < MiniTest::Test
|
12
|
+
|
13
|
+
def test_jsonx
|
14
|
+
|
15
|
+
sample1, exp1 = TestBlockFile.read_utf8( 'jsonx1' )
|
16
|
+
|
17
|
+
puts JSONX.convert( sample1 )
|
18
|
+
|
19
|
+
assert_equal eval(exp1), JSONX.parse( sample1 )
|
20
|
+
|
21
|
+
|
22
|
+
sample2, exp2 = TestBlockFile.read_utf8( 'jsonx2' )
|
23
|
+
|
24
|
+
puts JSONX.convert( sample2 )
|
25
|
+
|
26
|
+
assert_equal eval(exp2), JSONX.parse( sample2 )
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/test/test_parser_son.rb
CHANGED
@@ -11,31 +11,12 @@ require 'helper'
|
|
11
11
|
class TestParserSon < MiniTest::Test
|
12
12
|
|
13
13
|
def test_son
|
14
|
-
|
15
|
-
|
16
|
-
"fields"=>"mathematics",
|
17
|
-
"main_topics"=>
|
18
|
-
["Etale cohomology", "Motives", "Topos theory", "Schemes"]
|
19
|
-
}
|
20
|
-
|
21
|
-
sample1 =<<TXT
|
22
|
-
{
|
23
|
-
# Personal information
|
24
|
-
|
25
|
-
"name": "Alexander Grothendieck"
|
26
|
-
"fields": "mathematics"
|
27
|
-
"main_topics": [
|
28
|
-
"Etale cohomology"
|
29
|
-
"Motives"
|
30
|
-
"Topos theory"
|
31
|
-
"Schemes"
|
32
|
-
]
|
33
|
-
}
|
34
|
-
TXT
|
14
|
+
|
15
|
+
sample1, exp1 = TestBlockFile.read_utf8( 'son1' )
|
35
16
|
|
36
17
|
puts SON.convert( sample1 )
|
37
18
|
|
38
|
-
assert_equal
|
19
|
+
assert_equal eval(exp1), SON.parse( sample1 )
|
39
20
|
end
|
40
21
|
|
41
22
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json-next
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
@@ -39,8 +39,8 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.15'
|
41
41
|
description: json-next - read generation y / next generation json versions (HanSON,
|
42
|
-
SON, etc.) with comments, unquoted keys, multi-line strings, trailing
|
43
|
-
commas, and more
|
42
|
+
SON, JSONX/JSON11, etc.) with comments, unquoted keys, multi-line strings, trailing
|
43
|
+
commas, optional commas, and more
|
44
44
|
email: ruby-talk@ruby-lang.org
|
45
45
|
executables: []
|
46
46
|
extensions: []
|
@@ -56,12 +56,21 @@ files:
|
|
56
56
|
- lib/json/next.rb
|
57
57
|
- lib/json/next/commata.rb
|
58
58
|
- lib/json/next/parser/hanson.rb
|
59
|
+
- lib/json/next/parser/jsonx.rb
|
59
60
|
- lib/json/next/parser/son.rb
|
60
61
|
- lib/json/next/pattern.rb
|
61
62
|
- lib/json/next/version.rb
|
63
|
+
- test/data/commata1.txt
|
64
|
+
- test/data/commata2a.txt
|
65
|
+
- test/data/commata2b.txt
|
66
|
+
- test/data/hanson1.txt
|
67
|
+
- test/data/jsonx1.txt
|
68
|
+
- test/data/jsonx2.txt
|
69
|
+
- test/data/son1.txt
|
62
70
|
- test/helper.rb
|
63
71
|
- test/test_commata.rb
|
64
72
|
- test/test_parser_hanson.rb
|
73
|
+
- test/test_parser_jsonx.rb
|
65
74
|
- test/test_parser_son.rb
|
66
75
|
- test/test_version.rb
|
67
76
|
homepage: https://github.com/datatxt/json-next
|
@@ -90,6 +99,6 @@ rubygems_version: 2.6.7
|
|
90
99
|
signing_key:
|
91
100
|
specification_version: 4
|
92
101
|
summary: json-next - read generation y / next generation json versions (HanSON, SON,
|
93
|
-
etc.) with comments, unquoted keys, multi-line strings, trailing commas,
|
94
|
-
commas, and more
|
102
|
+
JSONX/JSON11, etc.) with comments, unquoted keys, multi-line strings, trailing commas,
|
103
|
+
optional commas, and more
|
95
104
|
test_files: []
|