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.

@@ -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.7
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
- ### Release 2.0.6
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 an undocumented feature in linux when using make that misreports the stack limits.
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
- ### Release 2.0.5
44
+ - All tests pass with Ruby 2.0.0-p0. Had to modify Exception encoding slightly.
45
45
 
46
- - DateTimes are now output the same in compat mode for both 1.8.7 and 1.9.3 even though they are implemented differently in each Ruby.
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
- - Added an option to allow BigDecimals to be dumped as either a string or as a number. There was no agreement on which
51
- was the best or correct so both are possible with the correct option setting.
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
 
@@ -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(rb_funcall(obj, oj_as_json_id, 0), depth, out);
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;
@@ -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 && (('1' == version[0] && '9' == version[1]) || '2' <= version[0])) ? 0 : 1,
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 => e
41
+ rescue Exception
42
42
  end
43
43
  else
44
44
  dflags['NEEDS_STPCPY'] = nil if is_windows
@@ -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 (neg) {
746
- return rb_float_new(-INFINITY);
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
- return rb_float_new(INFINITY);
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
 
@@ -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);
@@ -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
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '2.0.7'
4
+ VERSION = '2.0.8'
5
5
  end
@@ -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.7
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-02-18 00:00:00.000000000 Z
11
+ date: 2013-03-01 00:00:00.000000000 Z
13
12
  dependencies: []
14
- description: ! 'The fastest JSON parser and object serializer. '
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: 1.8.23
93
+ rubygems_version: 2.0.0
96
94
  signing_key:
97
- specification_version: 3
95
+ specification_version: 4
98
96
  summary: A fast JSON parser and serializer.
99
97
  test_files: []
100
98
  has_rdoc: true