oj 2.0.7 → 2.0.8
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oj might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/README.md +10 -12
- data/ext/oj/dump.c +37 -33
- data/ext/oj/extconf.rb +3 -3
- data/ext/oj/load.c +15 -4
- data/ext/oj/oj.c +8 -0
- data/ext/oj/oj.h +1 -0
- data/lib/oj/version.rb +1 -1
- data/test/tests.rb +10 -0
- metadata +8 -10
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 177a1133df5753c9fd378e44bcf2647c91f2cccf
|
4
|
+
data.tar.gz: d272392dbc1711664cb0aa7127a132ae46e76362
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5fbd4a3a406b90741f32a2b326035ebbcae1b92183bca17f2a3bf98b54bf14ea225e8c62139de84607a5505beb2e7d1450b1da91bd76d1d743d4aff52cef4ee5
|
7
|
+
data.tar.gz: 907088bc2d7a21f2624d23a317a21deeee6adb1bcf070d904652be25a103d4ad8a6952d2e458ec30666aaf1ccff05608845cc64a9076a6c812dfc0450a6569cc
|
data/README.md
CHANGED
@@ -32,23 +32,21 @@ A fast JSON parser and Object marshaller as a Ruby gem.
|
|
32
32
|
|
33
33
|
## <a name="release">Release Notes</a>
|
34
34
|
|
35
|
-
### Release 2.0.
|
36
|
-
|
37
|
-
- Fixed bug where undefined classes specified in a JSON document would freeze Ruby instead of raising an exception when
|
38
|
-
the auto_define option was not set. (It seems that Ruby freezes on trying to add variables to nil.)
|
35
|
+
### Release 2.0.8
|
39
36
|
|
40
|
-
|
37
|
+
- Added :bigdecimal_load option that forces all decimals in a JSON string to be read as BigDecimals instead of as
|
38
|
+
Floats. This is useful if precision is important.
|
41
39
|
|
42
|
-
- Worked around
|
40
|
+
- Worked around bug in active_support 2.3.x where BigDecimal.as_json() returned self instead of a JSON primitive. Of
|
41
|
+
course that creates a loop and blows the stack. Oj ignores the as_json() for any object that returns itself and
|
42
|
+
instead encodes the object as it sees fit which is usually what is expected.
|
43
43
|
|
44
|
-
|
44
|
+
- All tests pass with Ruby 2.0.0-p0. Had to modify Exception encoding slightly.
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
- Objects implemented as data structs can now change the encoding by implemented either to_json(), as_json(), or to_hash().
|
46
|
+
### Release 2.0.7
|
49
47
|
|
50
|
-
-
|
51
|
-
was
|
48
|
+
- Fixed bug where undefined classes specified in a JSON document would freeze Ruby instead of raising an exception when
|
49
|
+
the auto_define option was not set. (It seems that Ruby freezes on trying to add variables to nil.)
|
52
50
|
|
53
51
|
## <a name="description">Description</a>
|
54
52
|
|
data/ext/oj/dump.c
CHANGED
@@ -1117,6 +1117,8 @@ dump_data_null(VALUE obj, Out out) {
|
|
1117
1117
|
|
1118
1118
|
static void
|
1119
1119
|
dump_data_comp(VALUE obj, int depth, Out out) {
|
1120
|
+
VALUE o2;
|
1121
|
+
|
1120
1122
|
if (rb_respond_to(obj, oj_to_hash_id)) {
|
1121
1123
|
VALUE h = rb_funcall(obj, oj_to_hash_id, 0);
|
1122
1124
|
|
@@ -1124,8 +1126,8 @@ dump_data_comp(VALUE obj, int depth, Out out) {
|
|
1124
1126
|
rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
|
1125
1127
|
}
|
1126
1128
|
dump_hash(h, depth, out->opts->mode, out);
|
1127
|
-
} else if (rb_respond_to(obj, oj_as_json_id)) {
|
1128
|
-
dump_val(
|
1129
|
+
} else if (rb_respond_to(obj, oj_as_json_id) && obj != (o2 = rb_funcall(obj, oj_as_json_id, 0))) {
|
1130
|
+
dump_val(o2, depth, out);
|
1129
1131
|
} else if (rb_respond_to(obj, oj_to_json_id)) {
|
1130
1132
|
VALUE rs = rb_funcall(obj, oj_to_json_id, 0);
|
1131
1133
|
const char *s = StringValuePtr(rs);
|
@@ -1281,6 +1283,11 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
1281
1283
|
size_t size = depth * out->indent + 1;
|
1282
1284
|
const char *attr = rb_id2name(key);
|
1283
1285
|
|
1286
|
+
#if HAS_EXCEPTION_MAGIC
|
1287
|
+
if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
|
1288
|
+
return ST_CONTINUE;
|
1289
|
+
}
|
1290
|
+
#endif
|
1284
1291
|
if (out->end - out->cur <= (long)size) {
|
1285
1292
|
grow(out, size);
|
1286
1293
|
}
|
@@ -1369,6 +1376,34 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
|
|
1369
1376
|
}
|
1370
1377
|
#else
|
1371
1378
|
size = d2 * out->indent + 1;
|
1379
|
+
for (i = cnt; 0 < i; i--, np++) {
|
1380
|
+
if (out->end - out->cur <= (long)size) {
|
1381
|
+
grow(out, size);
|
1382
|
+
}
|
1383
|
+
vid = rb_to_id(*np);
|
1384
|
+
fill_indent(out, d2);
|
1385
|
+
attr = rb_id2name(vid);
|
1386
|
+
if ('@' == *attr) {
|
1387
|
+
attr++;
|
1388
|
+
dump_cstr(attr, strlen(attr), 0, 0, out);
|
1389
|
+
} else {
|
1390
|
+
char buf[32];
|
1391
|
+
|
1392
|
+
*buf = '~';
|
1393
|
+
strncpy(buf + 1, attr, sizeof(buf) - 2);
|
1394
|
+
buf[sizeof(buf) - 1] = '\0';
|
1395
|
+
dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
|
1396
|
+
}
|
1397
|
+
*out->cur++ = ':';
|
1398
|
+
dump_val(rb_ivar_get(obj, vid), d2, out);
|
1399
|
+
if (out->end - out->cur <= 2) {
|
1400
|
+
grow(out, 2);
|
1401
|
+
}
|
1402
|
+
if (1 < i) {
|
1403
|
+
*out->cur++ = ',';
|
1404
|
+
}
|
1405
|
+
}
|
1406
|
+
#endif
|
1372
1407
|
#if HAS_EXCEPTION_MAGIC
|
1373
1408
|
if (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) {
|
1374
1409
|
if (',' != *(out->cur - 1)) {
|
@@ -1397,37 +1432,6 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
|
|
1397
1432
|
if (out->end - out->cur <= 2) {
|
1398
1433
|
grow(out, 2);
|
1399
1434
|
}
|
1400
|
-
if (0 < cnt) {
|
1401
|
-
*out->cur++ = ',';
|
1402
|
-
}
|
1403
|
-
}
|
1404
|
-
#endif
|
1405
|
-
for (i = cnt; 0 < i; i--, np++) {
|
1406
|
-
if (out->end - out->cur <= (long)size) {
|
1407
|
-
grow(out, size);
|
1408
|
-
}
|
1409
|
-
vid = rb_to_id(*np);
|
1410
|
-
fill_indent(out, d2);
|
1411
|
-
attr = rb_id2name(vid);
|
1412
|
-
if ('@' == *attr) {
|
1413
|
-
attr++;
|
1414
|
-
dump_cstr(attr, strlen(attr), 0, 0, out);
|
1415
|
-
} else {
|
1416
|
-
char buf[32];
|
1417
|
-
|
1418
|
-
*buf = '~';
|
1419
|
-
strncpy(buf + 1, attr, sizeof(buf) - 2);
|
1420
|
-
buf[sizeof(buf) - 1] = '\0';
|
1421
|
-
dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
|
1422
|
-
}
|
1423
|
-
*out->cur++ = ':';
|
1424
|
-
dump_val(rb_ivar_get(obj, vid), d2, out);
|
1425
|
-
if (out->end - out->cur <= 2) {
|
1426
|
-
grow(out, 2);
|
1427
|
-
}
|
1428
|
-
if (1 < i) {
|
1429
|
-
*out->cur++ = ',';
|
1430
|
-
}
|
1431
1435
|
}
|
1432
1436
|
#endif
|
1433
1437
|
out->depth = depth;
|
data/ext/oj/extconf.rb
CHANGED
@@ -26,8 +26,8 @@ dflags = {
|
|
26
26
|
'HAS_NANO_TIME' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0,
|
27
27
|
'HAS_RSTRUCT' => ('ruby' == type || 'ree' == type || 'tcs-ruby' == type) ? 1 : 0,
|
28
28
|
'HAS_IVAR_HELPERS' => ('ruby' == type && !is_windows && (('1' == version[0] && '9' == version[1]) || '2' <= version[0])) ? 1 : 0,
|
29
|
-
'HAS_EXCEPTION_MAGIC' => ('ruby' == type && !is_windows && (
|
30
|
-
'HAS_PROC_WITH_BLOCK' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0,
|
29
|
+
'HAS_EXCEPTION_MAGIC' => ('ruby' == type && !is_windows && ('1' == version[0] && '9' == version[1])) ? 0 : 1,
|
30
|
+
'HAS_PROC_WITH_BLOCK' => ('ruby' == type && (('1' == version[0] && '9' == version[1]) || '2' <= version[0])) ? 1 : 0,
|
31
31
|
'HAS_TOP_LEVEL_ST_H' => ('ree' == type || ('ruby' == type && '1' == version[0] && '8' == version[1])) ? 1 : 0,
|
32
32
|
'IS_WINDOWS' => is_windows ? 1 : 0,
|
33
33
|
'SAFE_CACHE' => is_windows ? 0 : 1,
|
@@ -38,7 +38,7 @@ dflags = {
|
|
38
38
|
if 'x86_64-linux' == RUBY_PLATFORM && '1.9.3' == RUBY_VERSION && '2011-10-30' == RUBY_RELEASE_DATE
|
39
39
|
begin
|
40
40
|
dflags['NEEDS_STPCPY'] = nil if File.read('/etc/redhat-release').include?('CentOS release 5.4')
|
41
|
-
rescue Exception
|
41
|
+
rescue Exception
|
42
42
|
end
|
43
43
|
else
|
44
44
|
dflags['NEEDS_STPCPY'] = nil if is_windows
|
data/ext/oj/load.c
CHANGED
@@ -742,10 +742,21 @@ read_num(ParseInfo pi) {
|
|
742
742
|
raise_error("number or other value", pi->str, pi->s);
|
743
743
|
}
|
744
744
|
pi->s += 8;
|
745
|
-
if (
|
746
|
-
|
745
|
+
if (Yes == pi->options->bigdec_load) {
|
746
|
+
char c = *pi->s;
|
747
|
+
VALUE num;
|
748
|
+
|
749
|
+
*pi->s = '\0';
|
750
|
+
num = rb_funcall(oj_bigdecimal_class, oj_new_id, 1, rb_str_new2(start));
|
751
|
+
*pi->s = c;
|
752
|
+
|
753
|
+
return num;
|
747
754
|
} else {
|
748
|
-
|
755
|
+
if (neg) {
|
756
|
+
return rb_float_new(-INFINITY);
|
757
|
+
} else {
|
758
|
+
return rb_float_new(INFINITY);
|
759
|
+
}
|
749
760
|
}
|
750
761
|
}
|
751
762
|
for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
|
@@ -800,7 +811,7 @@ read_num(ParseInfo pi) {
|
|
800
811
|
return LONG2NUM(n);
|
801
812
|
}
|
802
813
|
} else { // decimal
|
803
|
-
if (big) {
|
814
|
+
if (big || Yes == pi->options->bigdec_load) {
|
804
815
|
char c = *pi->s;
|
805
816
|
VALUE num;
|
806
817
|
|
data/ext/oj/oj.c
CHANGED
@@ -85,6 +85,7 @@ VALUE oj_slash_string;
|
|
85
85
|
static VALUE ascii_only_sym;
|
86
86
|
static VALUE auto_define_sym;
|
87
87
|
static VALUE bigdecimal_as_decimal_sym;
|
88
|
+
static VALUE bigdecimal_load_sym;
|
88
89
|
static VALUE circular_sym;
|
89
90
|
static VALUE compat_sym;
|
90
91
|
static VALUE create_id_sym;
|
@@ -131,6 +132,7 @@ struct _Options oj_default_options = {
|
|
131
132
|
ObjectMode, // mode
|
132
133
|
UnixTime, // time_format
|
133
134
|
Yes, // bigdec_as_num
|
135
|
+
No, // bigdec_load
|
134
136
|
json_class, // create_id
|
135
137
|
65536, // max_stack
|
136
138
|
9, // sec_prec
|
@@ -162,6 +164,7 @@ oj_get_odd(VALUE clas) {
|
|
162
164
|
* - mode: [:object|:strict|:compat|:null] load and dump modes to use for JSON
|
163
165
|
* - time_format: [:unix|:xmlschema|:ruby] time format when dumping in :compat mode
|
164
166
|
* - bigdecimal_as_decimal: [true|false|nil] dump BigDecimal as a decimal number or as a String
|
167
|
+
* - bigdecimal_load: [true|false|nil] load decimals as BigDecimal instead of as a Float
|
165
168
|
* - create_id: [String|nil] create id for json compatible object encoding, default is 'json_create'
|
166
169
|
* - max_stack: [Fixnum|nil] maximum json size to allocate on the stack, default is 65536
|
167
170
|
* - second_precision: [Fixnum|nil] number of digits after the decimal when dumping the seconds portion of time
|
@@ -179,6 +182,7 @@ get_def_opts(VALUE self) {
|
|
179
182
|
rb_hash_aset(opts, ascii_only_sym, (Yes == oj_default_options.ascii_only) ? Qtrue : ((No == oj_default_options.ascii_only) ? Qfalse : Qnil));
|
180
183
|
rb_hash_aset(opts, symbol_keys_sym, (Yes == oj_default_options.sym_key) ? Qtrue : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
|
181
184
|
rb_hash_aset(opts, bigdecimal_as_decimal_sym, (Yes == oj_default_options.bigdec_as_num) ? Qtrue : ((No == oj_default_options.bigdec_as_num) ? Qfalse : Qnil));
|
185
|
+
rb_hash_aset(opts, bigdecimal_load_sym, (Yes == oj_default_options.bigdec_load) ? Qtrue : ((No == oj_default_options.bigdec_load) ? Qfalse : Qnil));
|
182
186
|
switch (oj_default_options.mode) {
|
183
187
|
case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
|
184
188
|
case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
|
@@ -207,6 +211,7 @@ get_def_opts(VALUE self) {
|
|
207
211
|
* @param [true|false|nil] :symbol_keys convert hash keys to symbols
|
208
212
|
* @param [true|false|nil] :ascii_only encode all high-bit characters as escaped sequences if true
|
209
213
|
* @param [true|false|nil] :bigdecimal_as_decimal dump BigDecimal as a decimal number or as a String
|
214
|
+
* @param [true|false|nil] :bigdecimal_load load decimals as a BigDecimal instead of as a Float
|
210
215
|
* @param [:object|:strict|:compat|:null] load and dump mode to use for JSON
|
211
216
|
* :strict raises an exception when a non-supported Object is
|
212
217
|
* encountered. :compat attempts to extract variable values from an
|
@@ -232,6 +237,7 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
232
237
|
{ symbol_keys_sym, &oj_default_options.sym_key },
|
233
238
|
{ ascii_only_sym, &oj_default_options.ascii_only },
|
234
239
|
{ bigdecimal_as_decimal_sym, &oj_default_options.bigdec_as_num },
|
240
|
+
{ bigdecimal_load_sym, &oj_default_options.bigdec_load },
|
235
241
|
{ Qnil, 0 }
|
236
242
|
};
|
237
243
|
YesNoOpt o;
|
@@ -337,6 +343,7 @@ parse_options(VALUE ropts, Options copts) {
|
|
337
343
|
{ symbol_keys_sym, &copts->sym_key },
|
338
344
|
{ ascii_only_sym, &copts->ascii_only },
|
339
345
|
{ bigdecimal_as_decimal_sym, &copts->bigdec_as_num },
|
346
|
+
{ bigdecimal_load_sym, &copts->bigdec_load },
|
340
347
|
{ Qnil, 0 }
|
341
348
|
};
|
342
349
|
YesNoOpt o;
|
@@ -1063,6 +1070,7 @@ void Init_oj() {
|
|
1063
1070
|
ascii_only_sym = ID2SYM(rb_intern("ascii_only")); rb_gc_register_address(&ascii_only_sym);
|
1064
1071
|
auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_gc_register_address(&auto_define_sym);
|
1065
1072
|
bigdecimal_as_decimal_sym = ID2SYM(rb_intern("bigdecimal_as_decimal"));rb_gc_register_address(&bigdecimal_as_decimal_sym);
|
1073
|
+
bigdecimal_load_sym = ID2SYM(rb_intern("bigdecimal_load"));rb_gc_register_address(&bigdecimal_load_sym);
|
1066
1074
|
circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
|
1067
1075
|
compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
|
1068
1076
|
create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
|
data/ext/oj/oj.h
CHANGED
@@ -109,6 +109,7 @@ typedef struct _Options {
|
|
109
109
|
char mode; // Mode
|
110
110
|
char time_format; // TimeFormat
|
111
111
|
char bigdec_as_num; // YesNo
|
112
|
+
char bigdec_load; // YesNo
|
112
113
|
const char *create_id; // 0 or string
|
113
114
|
size_t max_stack; // max size to allocate on the stack
|
114
115
|
int sec_prec; // second precision when dumping time
|
data/lib/oj/version.rb
CHANGED
data/test/tests.rb
CHANGED
@@ -118,6 +118,7 @@ class Juice < ::Test::Unit::TestCase
|
|
118
118
|
:mode=>:object,
|
119
119
|
:time_format=>:unix,
|
120
120
|
:bigdecimal_as_decimal=>true,
|
121
|
+
:bigdecimal_load=>false,
|
121
122
|
:max_stack=>65536,
|
122
123
|
:create_id=>'json_class'}, opts)
|
123
124
|
end
|
@@ -133,6 +134,7 @@ class Juice < ::Test::Unit::TestCase
|
|
133
134
|
:mode=>:object,
|
134
135
|
:time_format=>:unix,
|
135
136
|
:bigdecimal_as_decimal=>true,
|
137
|
+
:bigdecimal_load=>false,
|
136
138
|
:max_stack=>65536,
|
137
139
|
:create_id=>'json_class'}
|
138
140
|
o2 = {
|
@@ -145,6 +147,7 @@ class Juice < ::Test::Unit::TestCase
|
|
145
147
|
:mode=>:compat,
|
146
148
|
:time_format=>:ruby,
|
147
149
|
:bigdecimal_as_decimal=>false,
|
150
|
+
:bigdecimal_load=>true,
|
148
151
|
:max_stack=>4000,
|
149
152
|
:create_id=>nil}
|
150
153
|
o3 = { :indent => 4 }
|
@@ -743,6 +746,13 @@ class Juice < ::Test::Unit::TestCase
|
|
743
746
|
bg = Oj.load(json, :mode => :compat)
|
744
747
|
assert_equal(orig.to_s, bg)
|
745
748
|
end
|
749
|
+
def test_bigdecimal_load
|
750
|
+
orig = BigDecimal.new('80.51')
|
751
|
+
json = Oj.dump(orig, :mode => :compat, :bigdecimal_as_decimal => true)
|
752
|
+
bg = Oj.load(json, :mode => :compat, :bigdecimal_load => true)
|
753
|
+
assert_equal(BigDecimal, bg.class)
|
754
|
+
assert_equal(orig, bg)
|
755
|
+
end
|
746
756
|
def test_bigdecimal_compat_to_json
|
747
757
|
orig = BigDecimal.new('80.51')
|
748
758
|
BigDecimal.send(:define_method, :to_json) do
|
metadata
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
5
|
-
prerelease:
|
4
|
+
version: 2.0.8
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Peter Ohler
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-03-01 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
|
-
description:
|
13
|
+
description: 'The fastest JSON parser and object serializer. '
|
15
14
|
email: peter@ohler.com
|
16
15
|
executables: []
|
17
16
|
extensions:
|
@@ -71,6 +70,7 @@ files:
|
|
71
70
|
- README.md
|
72
71
|
homepage: http://www.ohler.com/oj
|
73
72
|
licenses: []
|
73
|
+
metadata: {}
|
74
74
|
post_install_message:
|
75
75
|
rdoc_options:
|
76
76
|
- --main
|
@@ -79,22 +79,20 @@ require_paths:
|
|
79
79
|
- lib
|
80
80
|
- ext
|
81
81
|
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
82
|
requirements:
|
84
|
-
- -
|
83
|
+
- - '>='
|
85
84
|
- !ruby/object:Gem::Version
|
86
85
|
version: '0'
|
87
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
-
none: false
|
89
87
|
requirements:
|
90
|
-
- -
|
88
|
+
- - '>='
|
91
89
|
- !ruby/object:Gem::Version
|
92
90
|
version: '0'
|
93
91
|
requirements: []
|
94
92
|
rubyforge_project: oj
|
95
|
-
rubygems_version:
|
93
|
+
rubygems_version: 2.0.0
|
96
94
|
signing_key:
|
97
|
-
specification_version:
|
95
|
+
specification_version: 4
|
98
96
|
summary: A fast JSON parser and serializer.
|
99
97
|
test_files: []
|
100
98
|
has_rdoc: true
|