oj 2.18.3 → 2.18.4
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/README.md +100 -83
- data/ext/oj/dump_custom.c +759 -0
- data/ext/oj/oj.c +10 -2
- data/ext/oj/oj.h +1 -0
- data/ext/oj/parse.c +7 -0
- data/lib/oj/version.rb +1 -1
- data/test/foo.rb +2 -19
- data/test/isolated/shared.rb +10 -4
- data/test/isolated/test_mimic_rails_after.rb +3 -3
- data/test/isolated/test_mimic_rails_before.rb +3 -3
- data/test/mem.rb +20 -0
- data/test/omit.rb +20 -0
- data/test/rails_datetime_test.rb +24 -0
- data/test/test_custom.rb +399 -0
- data/test/test_various.rb +22 -0
- data/test/test_writer.rb +16 -0
- data/test/x_test.rb +185 -0
- metadata +72 -69
- data/test/curl/curl_oj.rb +0 -46
- data/test/curl/get_oj.rb +0 -24
- data/test/curl/just_curl.rb +0 -31
- data/test/curl/just_oj.rb +0 -51
data/ext/oj/oj.c
CHANGED
@@ -130,6 +130,7 @@ static VALUE mode_sym;
|
|
130
130
|
static VALUE nan_sym;
|
131
131
|
static VALUE newline_sym;
|
132
132
|
static VALUE nilnil_sym;
|
133
|
+
static VALUE empty_string_sym;
|
133
134
|
static VALUE null_sym;
|
134
135
|
static VALUE object_sym;
|
135
136
|
static VALUE omit_nil_sym;
|
@@ -184,6 +185,7 @@ struct _Options oj_default_options = {
|
|
184
185
|
No, // to_json
|
185
186
|
No, // as_json
|
186
187
|
No, // nilnil
|
188
|
+
Yes, // empty_string
|
187
189
|
Yes, // allow_gc
|
188
190
|
Yes, // quirks_mode
|
189
191
|
No, // allow_invalid
|
@@ -231,6 +233,7 @@ static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
|
|
231
233
|
* - use_to_json: [true|false|nil] call to_json() methods on dump, default is false
|
232
234
|
* - use_as_json: [true|false|nil] call as_json() methods on dump, default is false
|
233
235
|
* - nilnil: [true|false|nil] if true a nil input to load will return nil and not raise an Exception
|
236
|
+
* - empty_string: [true|false|nil] if true an empty input will not raise an Exception
|
234
237
|
* - allow_gc: [true|false|nil] allow or prohibit GC during parsing, default is true (allow)
|
235
238
|
* - quirks_mode: [true,|false|nil] Allow single JSON values instead of documents, default is true (allow)
|
236
239
|
* - allow_invalid_unicode: [true,|false|nil] Allow invalid unicode, default is false (don't allow)
|
@@ -262,6 +265,7 @@ get_def_opts(VALUE self) {
|
|
262
265
|
rb_hash_aset(opts, use_to_json_sym, (Yes == oj_default_options.to_json) ? Qtrue : ((No == oj_default_options.to_json) ? Qfalse : Qnil));
|
263
266
|
rb_hash_aset(opts, use_as_json_sym, (Yes == oj_default_options.as_json) ? Qtrue : ((No == oj_default_options.as_json) ? Qfalse : Qnil));
|
264
267
|
rb_hash_aset(opts, nilnil_sym, (Yes == oj_default_options.nilnil) ? Qtrue : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
|
268
|
+
rb_hash_aset(opts, empty_string_sym, (Yes == oj_default_options.empty_string) ? Qtrue : ((No == oj_default_options.empty_string) ? Qfalse : Qnil));
|
265
269
|
rb_hash_aset(opts, allow_gc_sym, (Yes == oj_default_options.allow_gc) ? Qtrue : ((No == oj_default_options.allow_gc) ? Qfalse : Qnil));
|
266
270
|
rb_hash_aset(opts, quirks_mode_sym, (Yes == oj_default_options.quirks_mode) ? Qtrue : ((No == oj_default_options.quirks_mode) ? Qfalse : Qnil));
|
267
271
|
rb_hash_aset(opts, allow_invalid_unicode_sym, (Yes == oj_default_options.allow_invalid) ? Qtrue : ((No == oj_default_options.allow_invalid) ? Qfalse : Qnil));
|
@@ -378,6 +382,7 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
378
382
|
{ use_to_json_sym, &copts->to_json },
|
379
383
|
{ use_as_json_sym, &copts->as_json },
|
380
384
|
{ nilnil_sym, &copts->nilnil },
|
385
|
+
{ empty_string_sym, &copts->empty_string },
|
381
386
|
{ allow_gc_sym, &copts->allow_gc },
|
382
387
|
{ quirks_mode_sym, &copts->quirks_mode },
|
383
388
|
{ allow_invalid_unicode_sym, &copts->allow_invalid },
|
@@ -1525,7 +1530,7 @@ stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
1525
1530
|
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
|
1526
1531
|
break;
|
1527
1532
|
case 2:
|
1528
|
-
if (Qnil == argv[
|
1533
|
+
if (Qnil == argv[1]) {
|
1529
1534
|
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
|
1530
1535
|
} else {
|
1531
1536
|
rb_check_type(argv[1], T_STRING);
|
@@ -1805,7 +1810,7 @@ mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
1805
1810
|
|
1806
1811
|
strcpy(copts.dump_opts.indent_str, " ");
|
1807
1812
|
copts.dump_opts.indent_size = (uint8_t)strlen(copts.dump_opts.indent_str);
|
1808
|
-
strcpy(copts.dump_opts.before_sep, "
|
1813
|
+
strcpy(copts.dump_opts.before_sep, "");
|
1809
1814
|
copts.dump_opts.before_size = (uint8_t)strlen(copts.dump_opts.before_sep);
|
1810
1815
|
strcpy(copts.dump_opts.after_sep, " ");
|
1811
1816
|
copts.dump_opts.after_size = (uint8_t)strlen(copts.dump_opts.after_sep);
|
@@ -1832,6 +1837,7 @@ mimic_parse(int argc, VALUE *argv, VALUE self) {
|
|
1832
1837
|
pi.options.auto_define = No;
|
1833
1838
|
pi.options.quirks_mode = No;
|
1834
1839
|
pi.options.allow_invalid = No;
|
1840
|
+
pi.options.empty_string = No;
|
1835
1841
|
|
1836
1842
|
if (2 <= argc) {
|
1837
1843
|
VALUE ropts = argv[1];
|
@@ -1919,6 +1925,7 @@ static struct _Options mimic_object_to_json_options = {
|
|
1919
1925
|
No, // to_json
|
1920
1926
|
Yes, // as_json
|
1921
1927
|
Yes, // nilnil
|
1928
|
+
Yes, // empty_string
|
1922
1929
|
Yes, // allow_gc
|
1923
1930
|
Yes, // quirks_mode
|
1924
1931
|
No, // allow_invalid
|
@@ -2258,6 +2265,7 @@ void Init_oj() {
|
|
2258
2265
|
nan_sym = ID2SYM(rb_intern("nan")); rb_gc_register_address(&nan_sym);
|
2259
2266
|
newline_sym = ID2SYM(rb_intern("newline")); rb_gc_register_address(&newline_sym);
|
2260
2267
|
nilnil_sym = ID2SYM(rb_intern("nilnil")); rb_gc_register_address(&nilnil_sym);
|
2268
|
+
empty_string_sym = ID2SYM(rb_intern("empty_string"));rb_gc_register_address(&empty_string_sym);
|
2261
2269
|
null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
|
2262
2270
|
object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&object_nl_sym);
|
2263
2271
|
object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
|
data/ext/oj/oj.h
CHANGED
@@ -156,6 +156,7 @@ typedef struct _Options {
|
|
156
156
|
char to_json; // YesNo
|
157
157
|
char as_json; // YesNo
|
158
158
|
char nilnil; // YesNo
|
159
|
+
char empty_string; // YesNo
|
159
160
|
char allow_gc; // allow GC during parse
|
160
161
|
char quirks_mode; // allow single JSON values instead of documents
|
161
162
|
char allow_invalid; // YesNo - allow invalid unicode
|
data/ext/oj/parse.c
CHANGED
@@ -598,6 +598,13 @@ oj_parse2(ParseInfo pi) {
|
|
598
598
|
if (!first && '\0' != *pi->cur) {
|
599
599
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected characters after the JSON document");
|
600
600
|
}
|
601
|
+
|
602
|
+
// if no tokens are consumed (i.e. empty string), throw a parse error
|
603
|
+
// this is the behavior of JSON.parse in both Ruby and JS
|
604
|
+
if (No == pi->options.empty_string && 1 == first && '\0' == *pi->cur) {
|
605
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
|
606
|
+
}
|
607
|
+
|
601
608
|
switch (*pi->cur++) {
|
602
609
|
case '{':
|
603
610
|
hash_start(pi);
|
data/lib/oj/version.rb
CHANGED
data/test/foo.rb
CHANGED
@@ -1,24 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: UTF-8
|
3
3
|
|
4
|
-
$VERBOSE = true
|
5
|
-
|
6
|
-
here = File.expand_path(File.dirname(__FILE__))
|
7
4
|
$: << File.dirname(__FILE__)
|
8
|
-
$: << File.join(File.dirname(here), 'ext')
|
9
|
-
$: << File.join(File.dirname(here), 'lib')
|
10
|
-
|
11
|
-
require 'oj'
|
12
|
-
|
13
|
-
Oj.mimic_JSON()
|
14
|
-
|
15
|
-
class Foo
|
16
|
-
def as_json
|
17
|
-
{ foo: 'bar' }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
opts = {}
|
22
5
|
|
23
|
-
|
24
|
-
|
6
|
+
require 'test_strict'
|
7
|
+
require 'test_compat'
|
data/test/isolated/shared.rb
CHANGED
@@ -164,6 +164,12 @@ class SharedMimicTest < Minitest::Test
|
|
164
164
|
assert_raises(JSON::ParserError) { JSON.parse(json) }
|
165
165
|
end
|
166
166
|
|
167
|
+
def test_parse_with_empty_string
|
168
|
+
Oj.mimic_JSON
|
169
|
+
assert_raises(JSON::ParserError) { JSON.parse(' ') }
|
170
|
+
assert_raises(JSON::ParserError) { JSON.parse("\t\t\n ") }
|
171
|
+
end
|
172
|
+
|
167
173
|
# []
|
168
174
|
def test_bracket_load
|
169
175
|
json = %{{"a":1,"b":[true,false]}}
|
@@ -217,18 +223,18 @@ class SharedMimicTest < Minitest::Test
|
|
217
223
|
def test_pretty_generate
|
218
224
|
json = JSON.pretty_generate({ 'a' => 1, 'b' => [true, false]})
|
219
225
|
assert(%{{
|
220
|
-
"a"
|
221
|
-
"b"
|
226
|
+
"a": 1,
|
227
|
+
"b": [
|
222
228
|
true,
|
223
229
|
false
|
224
230
|
]
|
225
231
|
}} == json ||
|
226
232
|
%{{
|
227
|
-
"b"
|
233
|
+
"b": [
|
228
234
|
true,
|
229
235
|
false
|
230
236
|
],
|
231
|
-
"a"
|
237
|
+
"a": 1
|
232
238
|
}} == json)
|
233
239
|
end
|
234
240
|
|
@@ -7,9 +7,9 @@ require 'helper'
|
|
7
7
|
|
8
8
|
begin
|
9
9
|
require 'rails/all'
|
10
|
-
rescue
|
11
|
-
puts "
|
12
|
-
Process.exit
|
10
|
+
rescue LoadError => e
|
11
|
+
puts "Rails are not in the gemfile, skipping tests"
|
12
|
+
Process.exit
|
13
13
|
end
|
14
14
|
|
15
15
|
Oj.mimic_JSON
|
@@ -8,9 +8,9 @@ require 'helper'
|
|
8
8
|
Oj.mimic_JSON
|
9
9
|
begin
|
10
10
|
require 'rails/all'
|
11
|
-
rescue
|
12
|
-
puts "
|
13
|
-
Process.exit
|
11
|
+
rescue LoadError => e
|
12
|
+
puts "Rails are not in the gemfile, skipping tests"
|
13
|
+
Process.exit
|
14
14
|
end
|
15
15
|
|
16
16
|
require 'isolated/shared'
|
data/test/mem.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
|
+
|
7
|
+
require 'oj'
|
8
|
+
|
9
|
+
h = {
|
10
|
+
'a' => 1,
|
11
|
+
'b' => 2,
|
12
|
+
'c' => 3,
|
13
|
+
'd' => 4,
|
14
|
+
'e' => 5,
|
15
|
+
}
|
16
|
+
|
17
|
+
10000.times do
|
18
|
+
GC.start
|
19
|
+
Oj.dump(h)
|
20
|
+
end
|
data/test/omit.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
|
+
|
7
|
+
require 'oj'
|
8
|
+
require 'stringio'
|
9
|
+
require 'parallel'
|
10
|
+
|
11
|
+
h = { a: 1, b: nil, c: 3 }
|
12
|
+
outputs = Parallel.map((0...30).to_a, in_process: 30) do |i|
|
13
|
+
io = StringIO.new('wb+')
|
14
|
+
Oj.to_stream(io, h, omit_nil: false)
|
15
|
+
io.string
|
16
|
+
end
|
17
|
+
|
18
|
+
outputs.each do |output|
|
19
|
+
puts output
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << File.dirname(__FILE__)
|
5
|
+
|
6
|
+
%w(lib ext test).each do |dir|
|
7
|
+
$LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'sqlite3'
|
11
|
+
require "rails/all"
|
12
|
+
require "active_model"
|
13
|
+
|
14
|
+
date = DateTime.now
|
15
|
+
|
16
|
+
puts date.to_json
|
17
|
+
|
18
|
+
require "oj"
|
19
|
+
|
20
|
+
puts "OJ.dump(DateTime.now)"
|
21
|
+
puts
|
22
|
+
puts Oj.dump(DateTime.now)
|
23
|
+
puts
|
24
|
+
|
data/test/test_custom.rb
ADDED
@@ -0,0 +1,399 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << File.dirname(__FILE__)
|
5
|
+
|
6
|
+
=begin
|
7
|
+
require 'helper'
|
8
|
+
|
9
|
+
class CompatJuice < Minitest::Test
|
10
|
+
|
11
|
+
class Jeez
|
12
|
+
attr_accessor :x, :y
|
13
|
+
|
14
|
+
def initialize(x, y)
|
15
|
+
@x = x
|
16
|
+
@y = y
|
17
|
+
end
|
18
|
+
|
19
|
+
def eql?(o)
|
20
|
+
self.class == o.class && @x == o.x && @y == o.y
|
21
|
+
end
|
22
|
+
alias == eql?
|
23
|
+
|
24
|
+
def to_json()
|
25
|
+
{"json_class" => self.class.to_s,"x" => @x,"y" => @y}.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.json_create(h)
|
29
|
+
self.new(h['x'], h['y'])
|
30
|
+
end
|
31
|
+
end # Jeez
|
32
|
+
|
33
|
+
module One
|
34
|
+
module Two
|
35
|
+
module Three
|
36
|
+
class Deep
|
37
|
+
|
38
|
+
def initialize()
|
39
|
+
end
|
40
|
+
|
41
|
+
def eql?(o)
|
42
|
+
self.class == o.class
|
43
|
+
end
|
44
|
+
alias == eql?
|
45
|
+
|
46
|
+
def to_json(*a)
|
47
|
+
%{{"json_class":"#{self.class.name}"}}
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.json_create(h)
|
51
|
+
self.new()
|
52
|
+
end
|
53
|
+
end # Deep
|
54
|
+
end # Three
|
55
|
+
end # Two
|
56
|
+
end # One
|
57
|
+
|
58
|
+
def setup
|
59
|
+
@default_options = Oj.default_options
|
60
|
+
# in compat mode other options other than the JSON gem globals and options
|
61
|
+
# are not used.
|
62
|
+
Oj.default_options = { :mode => :compat }
|
63
|
+
end
|
64
|
+
|
65
|
+
def teardown
|
66
|
+
Oj.default_options = @default_options
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_nil
|
70
|
+
dump_and_load(nil, false)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_true
|
74
|
+
dump_and_load(true, false)
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_false
|
78
|
+
dump_and_load(false, false)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_fixnum
|
82
|
+
dump_and_load(0, false)
|
83
|
+
dump_and_load(12345, false)
|
84
|
+
dump_and_load(-54321, false)
|
85
|
+
dump_and_load(1, false)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_float
|
89
|
+
dump_and_load(0.0, false)
|
90
|
+
dump_and_load(12345.6789, false)
|
91
|
+
dump_and_load(70.35, false)
|
92
|
+
dump_and_load(-54321.012, false)
|
93
|
+
dump_and_load(1.7775, false)
|
94
|
+
dump_and_load(2.5024, false)
|
95
|
+
dump_and_load(2.48e16, false)
|
96
|
+
dump_and_load(2.48e100 * 1.0e10, false)
|
97
|
+
dump_and_load(-2.48e100 * 1.0e10, false)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_string
|
101
|
+
dump_and_load('', false)
|
102
|
+
dump_and_load('abc', false)
|
103
|
+
dump_and_load("abc\ndef", false)
|
104
|
+
dump_and_load("a\u0041", false)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_encode
|
108
|
+
opts = Oj.default_options
|
109
|
+
Oj.default_options = { :ascii_only => false }
|
110
|
+
unless 'jruby' == $ruby
|
111
|
+
dump_and_load("ぴーたー", false)
|
112
|
+
end
|
113
|
+
Oj.default_options = { :ascii_only => true }
|
114
|
+
json = Oj.dump("ぴーたー")
|
115
|
+
assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
|
116
|
+
unless 'jruby' == $ruby
|
117
|
+
dump_and_load("ぴーたー", false)
|
118
|
+
end
|
119
|
+
Oj.default_options = opts
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_unicode
|
123
|
+
# hits the 3 normal ranges and one extended surrogate pair
|
124
|
+
json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e"}
|
125
|
+
obj = Oj.load(json)
|
126
|
+
json2 = Oj.dump(obj, :ascii_only => true)
|
127
|
+
assert_equal(json, json2)
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_array
|
131
|
+
dump_and_load([], false)
|
132
|
+
dump_and_load([true, false], false)
|
133
|
+
dump_and_load(['a', 1, nil], false)
|
134
|
+
dump_and_load([[nil]], false)
|
135
|
+
dump_and_load([[nil], 58], false)
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_array_deep
|
139
|
+
dump_and_load([1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20]]]]]]]]]]]]]]]]]]]], false)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Hash
|
143
|
+
def test_hash
|
144
|
+
dump_and_load({}, false)
|
145
|
+
dump_and_load({ 'true' => true, 'false' => false}, false)
|
146
|
+
dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false)
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_hash_deep
|
150
|
+
dump_and_load({'1' => {
|
151
|
+
'2' => {
|
152
|
+
'3' => {
|
153
|
+
'4' => {
|
154
|
+
'5' => {
|
155
|
+
'6' => {
|
156
|
+
'7' => {
|
157
|
+
'8' => {
|
158
|
+
'9' => {
|
159
|
+
'10' => {
|
160
|
+
'11' => {
|
161
|
+
'12' => {
|
162
|
+
'13' => {
|
163
|
+
'14' => {
|
164
|
+
'15' => {
|
165
|
+
'16' => {
|
166
|
+
'17' => {
|
167
|
+
'18' => {
|
168
|
+
'19' => {
|
169
|
+
'20' => {}}}}}}}}}}}}}}}}}}}}}, false)
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_hash_escaped_key
|
173
|
+
json = %{{"a\nb":true,"c\td":false}}
|
174
|
+
obj = Oj.compat_load(json)
|
175
|
+
assert_equal({"a\nb" => true, "c\td" => false}, obj)
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_bignum_object
|
179
|
+
dump_and_load(7 ** 55, false)
|
180
|
+
end
|
181
|
+
|
182
|
+
# BigDecimal
|
183
|
+
def test_bigdecimal_compat
|
184
|
+
dump_and_load(BigDecimal.new('3.14159265358979323846'), false)
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_bigdecimal_load
|
188
|
+
orig = BigDecimal.new('80.51')
|
189
|
+
json = Oj.dump(orig, :mode => :compat, :bigdecimal_as_decimal => true)
|
190
|
+
bg = Oj.load(json, :mode => :compat, :bigdecimal_load => true)
|
191
|
+
assert_equal(BigDecimal, bg.class)
|
192
|
+
assert_equal(orig, bg)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Time
|
196
|
+
def test_time_ruby
|
197
|
+
if RUBY_VERSION.start_with?('1.8')
|
198
|
+
t = Time.parse('2015-01-05T21:37:07.123456-08:00')
|
199
|
+
else
|
200
|
+
t = Time.new(2015, 1, 5, 21, 37, 7.123456, -8 * 3600)
|
201
|
+
end
|
202
|
+
expect = '"' + t.to_s + '"'
|
203
|
+
json = Oj.dump(t, :mode => :compat, :time_format => :ruby)
|
204
|
+
assert_equal(expect, json)
|
205
|
+
end
|
206
|
+
def test_time_xml
|
207
|
+
if RUBY_VERSION.start_with?('1.8')
|
208
|
+
t = Time.parse('2015-01-05T21:37:07.123456-08:00')
|
209
|
+
else
|
210
|
+
t = Time.new(2015, 1, 5, 21, 37, 7.123456, -8 * 3600)
|
211
|
+
end
|
212
|
+
json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema, :second_precision => 6)
|
213
|
+
assert_equal('"2015-01-05T21:37:07.123456-08:00"', json)
|
214
|
+
end
|
215
|
+
unless RUBY_VERSION.start_with?('1.8')
|
216
|
+
def test_time_xml_12345
|
217
|
+
t = Time.new(2015, 1, 5, 21, 37, 7.123456, 12345)
|
218
|
+
json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema, :second_precision => 6)
|
219
|
+
assert_equal('"2015-01-05T21:37:07.123456+03:25"', json)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
def test_time_unix
|
223
|
+
if RUBY_VERSION.start_with?('1.8')
|
224
|
+
t = Time.parse('2015-01-05T21:37:07.123456-08:00')
|
225
|
+
else
|
226
|
+
t = Time.new(2015, 1, 5, 21, 37, 7.123456, -8 * 3600)
|
227
|
+
end
|
228
|
+
json = Oj.dump(t, :mode => :compat, :time_format => :unix, :second_precision => 6)
|
229
|
+
assert_equal('1420522627.123456', json)
|
230
|
+
end
|
231
|
+
def test_time_unix_zone
|
232
|
+
if RUBY_VERSION.start_with?('1.8')
|
233
|
+
t = Time.parse('2015-01-05T21:37:07.123456-08:00')
|
234
|
+
else
|
235
|
+
t = Time.new(2015, 1, 5, 21, 37, 7.123456, -8 * 3600)
|
236
|
+
end
|
237
|
+
json = Oj.dump(t, :mode => :compat, :time_format => :unix_zone, :second_precision => 6)
|
238
|
+
assert_equal('1420522627.123456e-28800', json)
|
239
|
+
end
|
240
|
+
unless RUBY_VERSION.start_with?('1.8')
|
241
|
+
def test_time_unix_zone_12345
|
242
|
+
t = Time.new(2015, 1, 5, 21, 37, 7.123456, 12345)
|
243
|
+
json = Oj.dump(t, :mode => :compat, :time_format => :unix_zone, :second_precision => 6)
|
244
|
+
assert_equal('1420481482.123456e12345', json)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
def test_time_unix_zone_early
|
248
|
+
if RUBY_VERSION.start_with?('1.8')
|
249
|
+
t = Time.parse('1954-01-05T21:37:07.123456-08:00')
|
250
|
+
else
|
251
|
+
t = Time.new(1954, 1, 5, 21, 37, 7.123456, -8 * 3600)
|
252
|
+
end
|
253
|
+
json = Oj.dump(t, :mode => :compat, :time_format => :unix_zone, :second_precision => 6)
|
254
|
+
assert_equal('-504469372.876544e-28800', json)
|
255
|
+
end
|
256
|
+
|
257
|
+
# Stream IO
|
258
|
+
def test_io_string
|
259
|
+
json = %{{
|
260
|
+
"x":true,
|
261
|
+
"y":58,
|
262
|
+
"z": [1,2,3]
|
263
|
+
}
|
264
|
+
}
|
265
|
+
input = StringIO.new(json)
|
266
|
+
obj = Oj.compat_load(input)
|
267
|
+
assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
|
268
|
+
end
|
269
|
+
|
270
|
+
def test_io_file
|
271
|
+
filename = File.join(File.dirname(__FILE__), 'open_file_test.json')
|
272
|
+
File.open(filename, 'w') { |f| f.write(%{{
|
273
|
+
"x":true,
|
274
|
+
"y":58,
|
275
|
+
"z": [1,2,3]
|
276
|
+
}
|
277
|
+
}) }
|
278
|
+
f = File.new(filename)
|
279
|
+
obj = Oj.compat_load(f)
|
280
|
+
f.close()
|
281
|
+
assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
|
282
|
+
end
|
283
|
+
|
284
|
+
# symbol_keys option
|
285
|
+
def test_symbol_keys
|
286
|
+
json = %{{
|
287
|
+
"x":true,
|
288
|
+
"y":58,
|
289
|
+
"z": [1,2,3]
|
290
|
+
}
|
291
|
+
}
|
292
|
+
obj = Oj.compat_load(json, :symbol_keys => true)
|
293
|
+
assert_equal({ :x => true, :y => 58, :z => [1, 2, 3]}, obj)
|
294
|
+
end
|
295
|
+
|
296
|
+
# comments
|
297
|
+
def test_comment_slash
|
298
|
+
json = %{{
|
299
|
+
"x":true,//three
|
300
|
+
"y":58,
|
301
|
+
"z": [1,2,
|
302
|
+
3 // six
|
303
|
+
]}
|
304
|
+
}
|
305
|
+
obj = Oj.compat_load(json)
|
306
|
+
assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_comment_c
|
310
|
+
json = %{{
|
311
|
+
"x"/*one*/:/*two*/true,
|
312
|
+
"y":58,
|
313
|
+
"z": [1,2,3]}
|
314
|
+
}
|
315
|
+
obj = Oj.compat_load(json)
|
316
|
+
assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
|
317
|
+
end
|
318
|
+
|
319
|
+
def test_comment
|
320
|
+
json = %{{
|
321
|
+
"x"/*one*/:/*two*/true,//three
|
322
|
+
"y":58/*four*/,
|
323
|
+
"z": [1,2/*five*/,
|
324
|
+
3 // six
|
325
|
+
]
|
326
|
+
}
|
327
|
+
}
|
328
|
+
obj = Oj.compat_load(json)
|
329
|
+
assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
|
330
|
+
end
|
331
|
+
|
332
|
+
def test_json_object_compat
|
333
|
+
obj = Jeez.new(true, 58)
|
334
|
+
Oj.default_options = { :mode => :compat, :use_as_json => true, :use_to_json => true }
|
335
|
+
dump_and_load(obj, false)
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_json_module_object
|
339
|
+
Oj.default_options = { :mode => :compat, :use_as_json => true, :use_to_json => true }
|
340
|
+
obj = One::Two::Three::Deep.new()
|
341
|
+
dump_and_load(obj, false)
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_json_object_create_id
|
345
|
+
Oj.default_options = { :mode => :compat, :use_as_json => false, :use_to_json => false }
|
346
|
+
expected = Jeez.new(true, 58)
|
347
|
+
json = Oj.dump(expected, :indent => 2, :mode => :compat, :use_to_json => true, :use_as_json => true)
|
348
|
+
obj = Oj.compat_load(json)
|
349
|
+
assert_equal(expected, obj)
|
350
|
+
end
|
351
|
+
|
352
|
+
def test_json_object_bad
|
353
|
+
json = %{{"json_class":"CompatJuice::Junk","x":true}}
|
354
|
+
begin
|
355
|
+
Oj.compat_load(json)
|
356
|
+
rescue Exception => e
|
357
|
+
assert_equal("Oj::ParseError", e.class().name)
|
358
|
+
return
|
359
|
+
end
|
360
|
+
assert(false, "*** expected an exception")
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_json_object_create_cache
|
364
|
+
Oj.default_options = { :mode => :compat, :use_as_json => true, :use_to_json => true }
|
365
|
+
expected = Jeez.new(true, 58)
|
366
|
+
json = Oj.dump(expected, :indent => 2, :mode => :compat, :use_to_json => true)
|
367
|
+
obj = Oj.compat_load(json, :class_cache => true)
|
368
|
+
assert_equal(expected, obj)
|
369
|
+
obj = Oj.compat_load(json, :class_cache => false)
|
370
|
+
assert_equal(expected, obj)
|
371
|
+
end
|
372
|
+
|
373
|
+
def test_json_object_create_id_other
|
374
|
+
Oj.default_options = { :mode => :compat, :use_as_json => false, :use_to_json => false }
|
375
|
+
expected = Jeez.new(true, 58)
|
376
|
+
json = Oj.dump(expected, :indent => 2, :mode => :compat, :use_as_json => true)
|
377
|
+
json.gsub!('json_class', '_class_')
|
378
|
+
obj = Oj.compat_load(json, :create_id => "_class_")
|
379
|
+
assert_equal(expected, obj)
|
380
|
+
end
|
381
|
+
|
382
|
+
def test_json_object_create_deep
|
383
|
+
Oj.default_options = { :mode => :compat, :use_as_json => true, :use_to_json => true }
|
384
|
+
expected = One::Two::Three::Deep.new()
|
385
|
+
json = Oj.dump(expected, :indent => 2, :mode => :compat)
|
386
|
+
obj = Oj.compat_load(json)
|
387
|
+
assert_equal(expected, obj)
|
388
|
+
end
|
389
|
+
|
390
|
+
def dump_and_load(obj, trace=false)
|
391
|
+
json = Oj.dump(obj, :indent => 2, :mode => :compat)
|
392
|
+
puts json if trace
|
393
|
+
loaded = Oj.compat_load(json);
|
394
|
+
assert_equal(obj, loaded)
|
395
|
+
loaded
|
396
|
+
end
|
397
|
+
|
398
|
+
end
|
399
|
+
=end
|