mongo-ejson 0.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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +39 -0
- data/README.md +57 -0
- data/Rakefile +26 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ejson.gemspec +46 -0
- data/lib/assets/ejson.js +4061 -0
- data/lib/ejson.rb +36 -0
- data/lib/ejson/parser_action/abstract.rb +9 -0
- data/lib/ejson/parser_action/abstract_json.rb +37 -0
- data/lib/ejson/parser_action/abstract_mongo.rb +36 -0
- data/lib/ejson/parser_action/bson.rb +61 -0
- data/lib/ejson/parser_action/ruby.rb +112 -0
- data/lib/ejson/parser_action/wrap.rb +44 -0
- data/lib/ejson/parser_action/wrap_types.rb +11 -0
- data/lib/ejson/rails.rb +1 -0
- data/lib/ejson/rails/engine.rb +6 -0
- data/lib/ejson/version.rb +3 -0
- data/src/ejson.peg +224 -0
- data/src/ejson.rb +4022 -0
- metadata +126 -0
data/lib/ejson.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative '../src/ejson.rb'
|
2
|
+
|
3
|
+
require 'ejson/parser_action/abstract'
|
4
|
+
require 'ejson/parser_action/wrap'
|
5
|
+
require 'ejson/parser_action/bson'
|
6
|
+
|
7
|
+
require 'ejson/version'
|
8
|
+
|
9
|
+
class EJSON
|
10
|
+
class << self
|
11
|
+
def validate(json_string)
|
12
|
+
ExtendedJSON.parse(json_string, actions: ParserAction::Abstract)
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse_bson(json_string)
|
16
|
+
boot_bson
|
17
|
+
|
18
|
+
ExtendedJSON.parse(json_string, actions: ParserAction::BSON.new)
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse_wrap(json_string)
|
22
|
+
ExtendedJSON.parse(json_string, actions: ParserAction::Wrap.new)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def boot_bson
|
27
|
+
return if defined? ::BSON
|
28
|
+
require 'bson' rescue nil
|
29
|
+
|
30
|
+
unless defined? ::BSON
|
31
|
+
raise "Can't find constant ::BSON. Seems like gem 'bson' is not " \
|
32
|
+
"loaded. Make sure it's available in your bundle."
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ParserAction
|
2
|
+
module AbstractJSON
|
3
|
+
# JSON Entities
|
4
|
+
def make_root(input, start, _end, elements)
|
5
|
+
end
|
6
|
+
|
7
|
+
def make_object(input, start, _end, elements)
|
8
|
+
end
|
9
|
+
|
10
|
+
def make_pair(input, start, _end, elements)
|
11
|
+
end
|
12
|
+
|
13
|
+
def make_empty_object(input, start, _end, elements)
|
14
|
+
end
|
15
|
+
|
16
|
+
def make_string(input, start, _end, elements)
|
17
|
+
end
|
18
|
+
|
19
|
+
def make_array(input, start, _end, elements)
|
20
|
+
end
|
21
|
+
|
22
|
+
def make_empty_array(input, start, _end, elements)
|
23
|
+
end
|
24
|
+
|
25
|
+
def make_number(input, start, _end, elements)
|
26
|
+
end
|
27
|
+
|
28
|
+
def make_null(input, start, _end)
|
29
|
+
end
|
30
|
+
|
31
|
+
def make_true(input, start, _end)
|
32
|
+
end
|
33
|
+
|
34
|
+
def make_false(input, start, _end)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ParserAction
|
2
|
+
module AbstractMongo
|
3
|
+
def make_object_id(input, start, _end, elements)
|
4
|
+
end
|
5
|
+
|
6
|
+
def make_bin_data(input, start, _end, elements)
|
7
|
+
end
|
8
|
+
|
9
|
+
def make_timestamp(input, start, _end, elements)
|
10
|
+
end
|
11
|
+
|
12
|
+
def make_number_long(input, start, _end, elements)
|
13
|
+
end
|
14
|
+
|
15
|
+
def make_number_decimal(input, start, _end, elements)
|
16
|
+
end
|
17
|
+
|
18
|
+
def make_date(input, start, _end, elements)
|
19
|
+
end
|
20
|
+
|
21
|
+
def make_regexp(input, start, _end, elements)
|
22
|
+
end
|
23
|
+
|
24
|
+
def make_db_ref(input, start, _end, elements)
|
25
|
+
end
|
26
|
+
|
27
|
+
def make_min_key(input, start, _end)
|
28
|
+
end
|
29
|
+
|
30
|
+
def make_max_key(input, start, _end)
|
31
|
+
end
|
32
|
+
|
33
|
+
def make_undefined(input, start, _end)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'ejson/parser_action/ruby'
|
2
|
+
|
3
|
+
module ParserAction
|
4
|
+
class BSON < ParserAction::Ruby
|
5
|
+
def make_object_id(input, start, _end, elements)
|
6
|
+
value = elements.first
|
7
|
+
|
8
|
+
::BSON::ObjectId.from_string(value)
|
9
|
+
end
|
10
|
+
|
11
|
+
NUMBER_TO_TYPE = {
|
12
|
+
0 => :generic,
|
13
|
+
1 => :function,
|
14
|
+
2 => :old,
|
15
|
+
3 => :uuid_old,
|
16
|
+
4 => :uuid,
|
17
|
+
5 => :md5,
|
18
|
+
128 => :user,
|
19
|
+
}
|
20
|
+
|
21
|
+
def make_bin_data(input, start, _end, elements)
|
22
|
+
data = elements.last
|
23
|
+
type = elements.first
|
24
|
+
|
25
|
+
if type.is_a? Numeric
|
26
|
+
type = NUMBER_TO_TYPE[type]
|
27
|
+
end
|
28
|
+
|
29
|
+
::BSON::Binary.new(data, type.to_sym)
|
30
|
+
end
|
31
|
+
|
32
|
+
def make_timestamp(input, start, _end, elements)
|
33
|
+
::BSON::Timestamp.new(elements.first, elements.last)
|
34
|
+
end
|
35
|
+
|
36
|
+
def make_number_decimal(input, start, _end, elements)
|
37
|
+
value = elements.first
|
38
|
+
|
39
|
+
::BSON::Decimal128.new(value.to_s)
|
40
|
+
end
|
41
|
+
|
42
|
+
def make_db_ref(input, start, _end, elements)
|
43
|
+
{
|
44
|
+
"$ref": elements.first,
|
45
|
+
"$id": elements.last,
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def make_min_key(input, start, _end)
|
50
|
+
::BSON::MinKey
|
51
|
+
end
|
52
|
+
|
53
|
+
def make_max_key(input, start, _end)
|
54
|
+
::BSON::MaxKey
|
55
|
+
end
|
56
|
+
|
57
|
+
def make_undefined(input, start, _end)
|
58
|
+
::BSON::Undefined
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'ejson/parser_action/abstract'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module ParserAction
|
5
|
+
class Ruby < ParserAction::Abstract
|
6
|
+
def make_root(input, start, _end, elements)
|
7
|
+
elements.first
|
8
|
+
end
|
9
|
+
|
10
|
+
def make_object(input, start, _end, elements)
|
11
|
+
first_pair = elements.first
|
12
|
+
other_pairs = elements.last
|
13
|
+
|
14
|
+
object = {first_pair[0] => first_pair[1]}
|
15
|
+
other_pairs.each do |element|
|
16
|
+
pair = element.pair
|
17
|
+
object[pair.first] = pair.last
|
18
|
+
end
|
19
|
+
|
20
|
+
object
|
21
|
+
end
|
22
|
+
|
23
|
+
def make_pair(input, start, _end, elements)
|
24
|
+
elements
|
25
|
+
end
|
26
|
+
|
27
|
+
def make_empty_object(input, start, _end, elements)
|
28
|
+
{}
|
29
|
+
end
|
30
|
+
|
31
|
+
def make_string(input, start, _end, elements)
|
32
|
+
%Q|"#{elements.first.text}"|.undump
|
33
|
+
end
|
34
|
+
|
35
|
+
def make_numeric_string(input, start, _end, elements)
|
36
|
+
elements.first
|
37
|
+
end
|
38
|
+
|
39
|
+
def make_number_as_string(input, start, _end, elements)
|
40
|
+
string = input[start..._end]
|
41
|
+
string.downcase!
|
42
|
+
|
43
|
+
string
|
44
|
+
end
|
45
|
+
|
46
|
+
def make_array(input, start, _end, elements)
|
47
|
+
list = [elements[0]]
|
48
|
+
elements[1].each { |el| list << el.value }
|
49
|
+
list
|
50
|
+
end
|
51
|
+
|
52
|
+
def make_empty_array(input, start, _end, elements)
|
53
|
+
[]
|
54
|
+
end
|
55
|
+
|
56
|
+
def make_number(input, start, _end, elements)
|
57
|
+
string = input[start..._end]
|
58
|
+
string.downcase!
|
59
|
+
|
60
|
+
_number_from_string(string)
|
61
|
+
end
|
62
|
+
|
63
|
+
def make_null(input, start, _end)
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def make_true(input, start, _end)
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
def make_false(input, start, _end)
|
72
|
+
false
|
73
|
+
end
|
74
|
+
|
75
|
+
# Makes ruby date from mongo Data type
|
76
|
+
def make_date(input, start, _end, elements)
|
77
|
+
value = elements.first
|
78
|
+
|
79
|
+
case value
|
80
|
+
when String
|
81
|
+
DateTime.parse(value)
|
82
|
+
when Numeric
|
83
|
+
Time.at(value)
|
84
|
+
else
|
85
|
+
raise ArgumentError,
|
86
|
+
"Internal parser error. Unknown date atom type #{value.class}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def make_regexp(input, start, _end, elements)
|
91
|
+
Regexp.new(elements.first.text, elements.last.text)
|
92
|
+
end
|
93
|
+
|
94
|
+
def make_number_long(input, start, _end, elements)
|
95
|
+
value = elements.first
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def _number_from_string(string)
|
101
|
+
if string.include? 'e'
|
102
|
+
return Float(string)
|
103
|
+
end
|
104
|
+
|
105
|
+
if string.include? '.'
|
106
|
+
string.to_f
|
107
|
+
else
|
108
|
+
string.to_i
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'ejson/parser_action/ruby'
|
2
|
+
require 'ejson/parser_action/wrap_types'
|
3
|
+
require 'bigdecimal'
|
4
|
+
|
5
|
+
module ParserAction
|
6
|
+
class Wrap < ParserAction::Ruby
|
7
|
+
def make_object_id(input, start, _end, elements)
|
8
|
+
value = elements.first
|
9
|
+
|
10
|
+
::Wrap::ObjectId.new(value)
|
11
|
+
end
|
12
|
+
|
13
|
+
def make_bin_data(input, start, _end, elements)
|
14
|
+
data = elements.last
|
15
|
+
type = elements.first
|
16
|
+
|
17
|
+
::Wrap::BinData.new(type, data)
|
18
|
+
end
|
19
|
+
|
20
|
+
def make_timestamp(input, start, _end, elements)
|
21
|
+
::Wrap::Timestamp.new(elements.first, elements.last)
|
22
|
+
end
|
23
|
+
|
24
|
+
def make_number_decimal(input, start, _end, elements)
|
25
|
+
BigDecimal(elements.first)
|
26
|
+
end
|
27
|
+
|
28
|
+
def make_db_ref(input, start, _end, elements)
|
29
|
+
::Wrap::DBRef.new(elements.first, elements.last)
|
30
|
+
end
|
31
|
+
|
32
|
+
def make_min_key(input, start, _end)
|
33
|
+
::Wrap::MinKey
|
34
|
+
end
|
35
|
+
|
36
|
+
def make_max_key(input, start, _end)
|
37
|
+
::Wrap::MaxKey
|
38
|
+
end
|
39
|
+
|
40
|
+
def make_undefined(input, start, _end)
|
41
|
+
::Wrap::Undefined
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Wrap
|
2
|
+
MinKey = Class.new
|
3
|
+
MaxKey = Class.new
|
4
|
+
Undefined = Class.new
|
5
|
+
|
6
|
+
ObjectId = Struct.new("ObjectId", :hex)
|
7
|
+
BinData = Struct.new("BinData", :type, :data)
|
8
|
+
Timestamp = Struct.new("Timestamp", :timestamp, :fraction)
|
9
|
+
|
10
|
+
DBRef = Struct.new("DBRef", :name, :id)
|
11
|
+
end
|
data/lib/ejson/rails.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'ejson/rails/engine'
|
data/src/ejson.peg
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
grammar ExtendedJSON
|
2
|
+
root <- @__ (object / array) @__
|
3
|
+
%make_root
|
4
|
+
|
5
|
+
object <- (non_empty_object / empty_object)
|
6
|
+
|
7
|
+
pair <- @__ string @assignment value
|
8
|
+
%make_pair
|
9
|
+
|
10
|
+
non_empty_object <- @object_open
|
11
|
+
pair (@delimiter pair)*
|
12
|
+
@object_close
|
13
|
+
%make_object
|
14
|
+
|
15
|
+
empty_object <- @object_open
|
16
|
+
@object_close
|
17
|
+
%make_empty_object
|
18
|
+
|
19
|
+
array <- non_empty_array / empty_array
|
20
|
+
|
21
|
+
non_empty_array <- @array_open
|
22
|
+
value (@delimiter value)*
|
23
|
+
@array_close
|
24
|
+
%make_array
|
25
|
+
|
26
|
+
empty_array <- @array_open
|
27
|
+
@array_close
|
28
|
+
%make_empty_array
|
29
|
+
|
30
|
+
value <- (json_values / mongo_literals / mongo_types)
|
31
|
+
|
32
|
+
json_values <- object / array / number / string / boolean / null
|
33
|
+
mongo_literals <- min_key / max_key / undefined / regexp_string
|
34
|
+
mongo_types <- object_id / bin_data / timestamp / number_long /
|
35
|
+
number_decimal / date / db_ref_type
|
36
|
+
|
37
|
+
# Values
|
38
|
+
boolean <- (true / false)
|
39
|
+
|
40
|
+
true <- "true"
|
41
|
+
%make_true
|
42
|
+
|
43
|
+
false <- "false"
|
44
|
+
%make_false
|
45
|
+
|
46
|
+
null <- "null"
|
47
|
+
%make_null
|
48
|
+
|
49
|
+
string <- double_quote_string / single_quote_string
|
50
|
+
|
51
|
+
double_quote_string <- @double_quote
|
52
|
+
("\\" . / [^"])*
|
53
|
+
@double_quote
|
54
|
+
%make_string
|
55
|
+
|
56
|
+
single_quote_string <- @single_quote
|
57
|
+
("\\" . / [^'])*
|
58
|
+
@single_quote
|
59
|
+
%make_string
|
60
|
+
|
61
|
+
hex_string <- hex_single_quote / hex_double_quote
|
62
|
+
hex_value <- [a-fA-F0-9]+
|
63
|
+
|
64
|
+
hex_single_quote <- @single_quote
|
65
|
+
hex_value
|
66
|
+
@single_quote
|
67
|
+
%make_string
|
68
|
+
|
69
|
+
hex_double_quote <- @double_quote
|
70
|
+
hex_value
|
71
|
+
@double_quote
|
72
|
+
%make_string
|
73
|
+
|
74
|
+
integer_string <- integer_string_single / integer_string_double
|
75
|
+
|
76
|
+
integer_string_single <- @single_quote
|
77
|
+
integer_number
|
78
|
+
@single_quote
|
79
|
+
%make_numeric_string
|
80
|
+
|
81
|
+
integer_string_double <- @double_quote
|
82
|
+
integer_number
|
83
|
+
@double_quote
|
84
|
+
%make_numeric_string
|
85
|
+
|
86
|
+
number_string <- number_string_single / number_string_double
|
87
|
+
|
88
|
+
number_string_single <- @single_quote
|
89
|
+
number
|
90
|
+
@single_quote
|
91
|
+
%make_numeric_string
|
92
|
+
|
93
|
+
number_string_double <- @double_quote
|
94
|
+
number
|
95
|
+
@double_quote
|
96
|
+
%make_numeric_string
|
97
|
+
|
98
|
+
regexp_string <- @slash
|
99
|
+
("\\" . / [^\/])*
|
100
|
+
@slash
|
101
|
+
regexp_options?
|
102
|
+
%make_regexp
|
103
|
+
|
104
|
+
regexp_options <- [gims]+
|
105
|
+
|
106
|
+
base64_string <- base64_single_quote / base64_dobule_quote
|
107
|
+
|
108
|
+
base64_value <- [a-zA-Z0-9+\/]+ ("=" / "==")?
|
109
|
+
|
110
|
+
base64_single_quote <- @single_quote
|
111
|
+
base64_value
|
112
|
+
@single_quote
|
113
|
+
%make_string
|
114
|
+
|
115
|
+
base64_dobule_quote <- @double_quote
|
116
|
+
base64_value
|
117
|
+
@double_quote
|
118
|
+
%make_string
|
119
|
+
|
120
|
+
number <- "-"? integer fraction? exponent?
|
121
|
+
%make_number
|
122
|
+
|
123
|
+
number_as_string <- "-"? integer fraction? exponent?
|
124
|
+
%make_number_as_string
|
125
|
+
|
126
|
+
integer <- ("0" / [1-9] [0-9]*)
|
127
|
+
fraction <- ("." [0-9]+)
|
128
|
+
exponent <- (("e" / "E") ("+" / "-" / "") [0-9]+)
|
129
|
+
|
130
|
+
integer_number <- integer @""
|
131
|
+
%make_number
|
132
|
+
|
133
|
+
# Mongo Extensions
|
134
|
+
|
135
|
+
min_key <- "MinKey"
|
136
|
+
%make_min_key
|
137
|
+
|
138
|
+
max_key <- "MaxKey"
|
139
|
+
%make_max_key
|
140
|
+
|
141
|
+
undefined <- "undefined"
|
142
|
+
%make_undefined
|
143
|
+
|
144
|
+
object_id <- @"ObjectId"
|
145
|
+
@type_open
|
146
|
+
hex_string
|
147
|
+
@type_close
|
148
|
+
%make_object_id
|
149
|
+
|
150
|
+
bin_data_type <- string / integer_number
|
151
|
+
bin_data <- @"BinData"
|
152
|
+
@type_open
|
153
|
+
bin_data_type
|
154
|
+
@delimiter
|
155
|
+
base64_string
|
156
|
+
@type_close
|
157
|
+
%make_bin_data
|
158
|
+
|
159
|
+
timestamp <- @"Timestamp"
|
160
|
+
@type_open
|
161
|
+
integer_number
|
162
|
+
@delimiter
|
163
|
+
integer_number
|
164
|
+
@type_close
|
165
|
+
%make_timestamp
|
166
|
+
|
167
|
+
number_long_value <- integer_number / integer_string
|
168
|
+
number_long <- @"NumberLong"
|
169
|
+
@type_open
|
170
|
+
number_long_value
|
171
|
+
@type_close
|
172
|
+
%make_number_long
|
173
|
+
|
174
|
+
|
175
|
+
number_decimal_value <- number_as_string / number_string
|
176
|
+
number_decimal <- @"NumberDecimal"
|
177
|
+
@type_open
|
178
|
+
number_decimal_value
|
179
|
+
@type_close
|
180
|
+
%make_number_decimal
|
181
|
+
|
182
|
+
date_type <- ("new" space+ "Date" / "ISODate")
|
183
|
+
date_value <- integer_number / string
|
184
|
+
date <- @date_type
|
185
|
+
@type_open
|
186
|
+
date_value
|
187
|
+
@type_close
|
188
|
+
%make_date
|
189
|
+
|
190
|
+
db_ref_type <- @"DBRef"
|
191
|
+
@type_open
|
192
|
+
string
|
193
|
+
@delimiter
|
194
|
+
string
|
195
|
+
@type_close
|
196
|
+
%make_db_ref
|
197
|
+
|
198
|
+
single_quote <- "'"
|
199
|
+
double_quote <- '"'
|
200
|
+
left_paren <- '('
|
201
|
+
right_paren <- ')'
|
202
|
+
left_brace <- '{'
|
203
|
+
right_brace <- '}'
|
204
|
+
left_bracket <- '['
|
205
|
+
right_bracket <- ']'
|
206
|
+
comma <- ','
|
207
|
+
colon <- ':'
|
208
|
+
slash <- '/'
|
209
|
+
space <- [\s]
|
210
|
+
new_line <- [\n]
|
211
|
+
|
212
|
+
comment <- "//" [^\n]*
|
213
|
+
__ <- (space / new_line / comment)*
|
214
|
+
|
215
|
+
delimiter <- @__ comma @__
|
216
|
+
assignment <- @__ @colon @__
|
217
|
+
|
218
|
+
object_open <- @__ @left_brace @__
|
219
|
+
object_close <- @__ @right_brace @__
|
220
|
+
array_open <- @__ @left_bracket @__
|
221
|
+
array_close <- @__ @right_bracket @__
|
222
|
+
|
223
|
+
type_open <- @space* @left_paren @space*
|
224
|
+
type_close <- @space* @right_paren
|