json-next 1.1.0 → 1.2.0
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/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
|

|
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: []
|