oj 2.16.1 → 2.17.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a459214e273fcd3594396cd6c4129edf08ddfcab
4
- data.tar.gz: 41458eb90534006c7d8659ed98e9266172641f4e
3
+ metadata.gz: 0e2063d3f596d87dc90d95f4bd8446794bc88cc7
4
+ data.tar.gz: 0d02aaf101d0bc855a41d5bae232a971f62179e5
5
5
  SHA512:
6
- metadata.gz: 60e8acd2f5fa2f4653240075d2e97f116057c730501109e14a7a5295b2b90c6503b9d1e236a7805fbffeebae30b69d0b4af73dcd2e43aa1c8b11c97975a39d67
7
- data.tar.gz: 1eb7d70e47b0cd512a1ce19539e89a301537080bd22b165f38b5f0fc89340eeb10239bb09bda9f8882fb2fafbc78187828f403ef1ab7a8625a189181127d6e44
6
+ metadata.gz: 61cb345cc92849ec10dc8c1498881479b58e563efaee5733ac511ca0c609fc3d50bcb1edff2d933b94d2c1f73390e243fb8802a67ce6b7106daa97c90ad37085
7
+ data.tar.gz: a3d2637aac496158e101ba16b4831ed5bed7abaf9ec3b57bcc58e87fe3cefaa6e4793ff959d5f34e8dde02d2158e1bf6f76907d2bb5dfe692332b564498fc483
data/README.md CHANGED
@@ -170,6 +170,18 @@ Oj.default_options = {:mode => :compat }
170
170
 
171
171
  ## Releases
172
172
 
173
+ **Release 2.17.0**
174
+
175
+ - Added an option provide an alternative Hash class for loading.
176
+
177
+ - Added the Oj::EasyHash class.
178
+
179
+ - Fixed test failures on 32 bit machines.
180
+
181
+ - Sped up mimic_JSON.
182
+
183
+ - Added an option to omit Hash and Object attributes with nil values.
184
+
173
185
  **Release 2.16.1**
174
186
 
175
187
  - Thanks to hsbt for fixing a compile issue with Ruby 2.4.0-preview1.
@@ -834,6 +834,9 @@ hash_cb_strict(VALUE key, VALUE value, Out out) {
834
834
  if (rb_type(key) != T_STRING) {
835
835
  rb_raise(rb_eTypeError, "In :strict mode all Hash keys must be Strings, not %s.\n", rb_class2name(rb_obj_class(key)));
836
836
  }
837
+ if (out->omit_nil && Qnil == value) {
838
+ return ST_CONTINUE;
839
+ }
837
840
  if (!out->opts->dump_opts.use) {
838
841
  size = depth * out->indent + 1;
839
842
  if (out->end - out->cur <= size) {
@@ -885,6 +888,9 @@ hash_cb_compat(VALUE key, VALUE value, Out out) {
885
888
  int depth = out->depth;
886
889
  long size;
887
890
 
891
+ if (out->omit_nil && Qnil == value) {
892
+ return ST_CONTINUE;
893
+ }
888
894
  if (!out->opts->dump_opts.use) {
889
895
  size = depth * out->indent + 1;
890
896
  if (out->end - out->cur <= size) {
@@ -949,6 +955,9 @@ hash_cb_object(VALUE key, VALUE value, Out out) {
949
955
  int depth = out->depth;
950
956
  long size = depth * out->indent + 1;
951
957
 
958
+ if (out->omit_nil && Qnil == value) {
959
+ return ST_CONTINUE;
960
+ }
952
961
  if (out->end - out->cur <= size) {
953
962
  grow(out, size);
954
963
  }
@@ -1424,7 +1433,7 @@ static void
1424
1433
  dump_obj_comp(VALUE obj, int depth, Out out, int argc, VALUE *argv) {
1425
1434
  if (rb_respond_to(obj, oj_to_hash_id)) {
1426
1435
  volatile VALUE h = rb_funcall(obj, oj_to_hash_id, 0);
1427
-
1436
+
1428
1437
  if (T_HASH != rb_type(h)) {
1429
1438
  // It seems that ActiveRecord implemented to_hash so that it returns
1430
1439
  // an Array and not a Hash. To get around that any value returned
@@ -1534,6 +1543,9 @@ dump_attr_cb(ID key, VALUE value, Out out) {
1534
1543
  size_t size = depth * out->indent + 1;
1535
1544
  const char *attr = rb_id2name(key);
1536
1545
 
1546
+ if (out->omit_nil && Qnil == value) {
1547
+ return ST_CONTINUE;
1548
+ }
1537
1549
  #if HAS_EXCEPTION_MAGIC
1538
1550
  if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
1539
1551
  return ST_CONTINUE;
@@ -1681,6 +1693,8 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
1681
1693
  #else
1682
1694
  size = d2 * out->indent + 1;
1683
1695
  for (i = cnt; 0 < i; i--, np++) {
1696
+ VALUE value;
1697
+
1684
1698
  vid = rb_to_id(*np);
1685
1699
  attr = rb_id2name(vid);
1686
1700
  #ifdef RUBINIUS_RUBY
@@ -1688,6 +1702,10 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
1688
1702
  continue;
1689
1703
  }
1690
1704
  #endif
1705
+ value = rb_ivar_get(obj, vid);
1706
+ if (out->omit_nil && Qnil == value) {
1707
+ continue;
1708
+ }
1691
1709
  if (first) {
1692
1710
  first = 0;
1693
1711
  } else {
@@ -1709,7 +1727,7 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
1709
1727
  dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
1710
1728
  }
1711
1729
  *out->cur++ = ':';
1712
- dump_val(rb_ivar_get(obj, vid), d2, out, 0, 0);
1730
+ dump_val(value, d2, out, 0, 0);
1713
1731
  if (out->end - out->cur <= 2) {
1714
1732
  grow(out, 2);
1715
1733
  }
@@ -2175,6 +2193,7 @@ oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
2175
2193
  out.buf = buf;
2176
2194
  out.end = buf + sizeof(buf) - BUFFER_EXTRA;
2177
2195
  out.allocated = 0;
2196
+ out.omit_nil = copts->dump_opts.omit_nil;
2178
2197
  oj_dump_obj_to_json(obj, copts, &out);
2179
2198
  size = out.cur - out.buf;
2180
2199
  if (0 == (f = fopen(path, "w"))) {
@@ -2210,6 +2229,7 @@ oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
2210
2229
  out.end = buf + sizeof(buf) - BUFFER_EXTRA;
2211
2230
  out.allocated = 0;
2212
2231
  oj_dump_obj_to_json(obj, copts, &out);
2232
+ out.omit_nil = copts->dump_opts.omit_nil;
2213
2233
  size = out.cur - out.buf;
2214
2234
  if (oj_stringio_class == clas) {
2215
2235
  rb_funcall(stream, oj_write_id, 1, rb_str_new(out.buf, size));
@@ -2438,6 +2458,7 @@ oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts) {
2438
2458
  out.end = buf + sizeof(buf) - BUFFER_EXTRA;
2439
2459
  out.allocated = 0;
2440
2460
  oj_dump_leaf_to_json(leaf, copts, &out);
2461
+ out.omit_nil = copts->dump_opts.omit_nil;
2441
2462
  size = out.cur - out.buf;
2442
2463
  if (0 == (f = fopen(path, "w"))) {
2443
2464
  rb_raise(rb_eIOError, "%s\n", strerror(errno));
@@ -1543,6 +1543,7 @@ doc_dump(int argc, VALUE *argv, VALUE self) {
1543
1543
  out.buf = buf;
1544
1544
  out.end = buf + sizeof(buf) - 10;
1545
1545
  out.allocated = 0;
1546
+ out.omit_nil = oj_default_options.dump_opts.omit_nil;
1546
1547
  oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
1547
1548
  rjson = rb_str_new2(out.buf);
1548
1549
  if (out.allocated) {
@@ -121,6 +121,7 @@ static VALUE create_id_sym;
121
121
  static VALUE escape_mode_sym;
122
122
  static VALUE float_prec_sym;
123
123
  static VALUE float_sym;
124
+ static VALUE hash_class_sym;
124
125
  static VALUE huge_sym;
125
126
  static VALUE indent_sym;
126
127
  static VALUE json_parser_error_class;
@@ -131,6 +132,7 @@ static VALUE newline_sym;
131
132
  static VALUE nilnil_sym;
132
133
  static VALUE null_sym;
133
134
  static VALUE object_sym;
135
+ static VALUE omit_nil_sym;
134
136
  static VALUE quirks_mode_sym;
135
137
  static VALUE raise_sym;
136
138
  static VALUE ruby_sym;
@@ -188,6 +190,7 @@ struct _Options oj_default_options = {
188
190
  9, // sec_prec
189
191
  15, // float_prec
190
192
  "%0.15g", // float_fmt
193
+ Qnil, // hash_class
191
194
  { // dump_opts
192
195
  false, //use
193
196
  "", // indent
@@ -201,6 +204,7 @@ struct _Options oj_default_options = {
201
204
  0, // hash_size
202
205
  0, // array_size
203
206
  AutoNan,// nan_dump
207
+ false, // omit_nil
204
208
  }
205
209
  };
206
210
 
@@ -233,6 +237,8 @@ static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
233
237
  * - object_nl: [String|nil] String to use after a JSON object field value
234
238
  * - array_nl: [String|nil] String to use after a JSON array value
235
239
  * - nan: [:null|:huge|:word|:raise|:auto] how to dump Infinity and NaN in null, strict, and compat mode. :null places a null, :huge places a huge number, :word places Infinity or NaN, :raise raises and exception, :auto uses default for each mode.
240
+ * - hash_class: [Class|nil] Class to use instead of Hash on load
241
+ * - omit_nil: [true|false] if true Hash and Object attributes with nil values are omitted
236
242
  * @return [Hash] all current option settings.
237
243
  */
238
244
  static VALUE
@@ -297,6 +303,9 @@ get_def_opts(VALUE self) {
297
303
  case AutoNan:
298
304
  default: rb_hash_aset(opts, nan_sym, auto_sym); break;
299
305
  }
306
+ rb_hash_aset(opts, omit_nil_sym, oj_default_options.dump_opts.omit_nil ? Qtrue : Qfalse);
307
+ rb_hash_aset(opts, hash_class_sym, oj_default_options.hash_class);
308
+
300
309
  return opts;
301
310
  }
302
311
 
@@ -341,6 +350,8 @@ get_def_opts(VALUE self) {
341
350
  * @param [String|nil] :object_nl String to use after a JSON object field value
342
351
  * @param [String|nil] :array_nl String to use after a JSON array value
343
352
  * @param [:null|:huge|:word|:raise] :nan how to dump Infinity and NaN in null, strict, and compat mode. :null places a null, :huge places a huge number, :word places Infinity or NaN, :raise raises and exception, :auto uses default for each mode.
353
+ * @param [Class|nil] :hash_class Class to use instead of Hash on load
354
+ * @param [true|false] :omit_nil if true Hash and Object attributes with nil values are omitted
344
355
  * @return [nil]
345
356
  */
346
357
  static VALUE
@@ -599,6 +610,15 @@ oj_parse_options(VALUE ropts, Options copts) {
599
610
  0 < copts->dump_opts.before_size ||
600
611
  0 < copts->dump_opts.hash_size ||
601
612
  0 < copts->dump_opts.array_size);
613
+ if (Qnil != (v = rb_hash_lookup(ropts, omit_nil_sym))) {
614
+ if (Qtrue == v) {
615
+ copts->dump_opts.omit_nil = true;
616
+ } else if (Qfalse == v) {
617
+ copts->dump_opts.omit_nil = false;
618
+ } else {
619
+ rb_raise(rb_eArgError, ":omit_nil must be true or false.");
620
+ }
621
+ }
602
622
  // This is here only for backwards compatibility with the original Oj.
603
623
  v = rb_hash_lookup(ropts, ascii_only_sym);
604
624
  if (Qtrue == v) {
@@ -606,6 +626,14 @@ oj_parse_options(VALUE ropts, Options copts) {
606
626
  } else if (Qfalse == v) {
607
627
  copts->escape_mode = JSONEsc;
608
628
  }
629
+ if (Qtrue == rb_funcall(ropts, has_key_id, 1, hash_class_sym)) {
630
+ if (Qnil == (v = rb_hash_lookup(ropts, hash_class_sym))) {
631
+ copts->hash_class = Qnil;
632
+ } else {
633
+ rb_check_type(v, T_CLASS);
634
+ copts->hash_class = v;
635
+ }
636
+ }
609
637
  }
610
638
 
611
639
  /* Document-method: strict_load
@@ -910,6 +938,7 @@ dump(int argc, VALUE *argv, VALUE self) {
910
938
  out.buf = buf;
911
939
  out.end = buf + sizeof(buf) - 10;
912
940
  out.allocated = 0;
941
+ out.omit_nil = copts.dump_opts.omit_nil;
913
942
  oj_dump_obj_to_json(*argv, &copts, &out);
914
943
  if (0 == out.buf) {
915
944
  rb_raise(rb_eNoMemError, "Not enough memory.");
@@ -1579,6 +1608,7 @@ mimic_dump(int argc, VALUE *argv, VALUE self) {
1579
1608
  out.buf = buf;
1580
1609
  out.end = buf + sizeof(buf) - 10;
1581
1610
  out.allocated = 0;
1611
+ out.omit_nil = copts.dump_opts.omit_nil;
1582
1612
  oj_dump_obj_to_json(*argv, &copts, &out);
1583
1613
  if (0 == out.buf) {
1584
1614
  rb_raise(rb_eNoMemError, "Not enough memory.");
@@ -1676,6 +1706,7 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
1676
1706
  out.buf = buf;
1677
1707
  out.end = buf + sizeof(buf) - 10;
1678
1708
  out.allocated = 0;
1709
+ out.omit_nil = copts->dump_opts.omit_nil;
1679
1710
  if (2 == argc && Qnil != argv[1]) {
1680
1711
  VALUE ropts = argv[1];
1681
1712
  VALUE v;
@@ -1870,6 +1901,7 @@ static struct _Options mimic_object_to_json_options = {
1870
1901
  9, // sec_prec
1871
1902
  15, // float_prec
1872
1903
  "%0.15g", // float_fmt
1904
+ Qnil, // hash_class
1873
1905
  { // dump_opts
1874
1906
  false, //use
1875
1907
  "", // indent
@@ -1883,6 +1915,7 @@ static struct _Options mimic_object_to_json_options = {
1883
1915
  0, // hash_size
1884
1916
  0, // array_size
1885
1917
  AutoNan,// nan_dump
1918
+ false, // omit_nil
1886
1919
  }
1887
1920
  };
1888
1921
 
@@ -1896,6 +1929,7 @@ mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
1896
1929
  out.buf = buf;
1897
1930
  out.end = buf + sizeof(buf) - 10;
1898
1931
  out.allocated = 0;
1932
+ out.omit_nil = copts.dump_opts.omit_nil;
1899
1933
  // Have to turn off to_json to avoid the Active Support recursion problem.
1900
1934
  copts.to_json = No;
1901
1935
  // To be strict the mimic_object_to_json_options should be used but people
@@ -1932,6 +1966,7 @@ static VALUE
1932
1966
  define_mimic_json(int argc, VALUE *argv, VALUE self) {
1933
1967
  VALUE ext;
1934
1968
  VALUE dummy;
1969
+ VALUE verbose;
1935
1970
  VALUE json_error;
1936
1971
 
1937
1972
  // Either set the paths to indicate JSON has been loaded or replaces the
@@ -1941,6 +1976,8 @@ define_mimic_json(int argc, VALUE *argv, VALUE self) {
1941
1976
  } else {
1942
1977
  mimic = rb_define_module("JSON");
1943
1978
  }
1979
+ verbose = rb_gv_get("$VERBOSE");
1980
+ rb_gv_set("$VERBOSE", Qfalse);
1944
1981
  rb_define_module_function(rb_cObject, "JSON", mimic_dump_load, -1);
1945
1982
  if (rb_const_defined_at(mimic, rb_intern("Ext"))) {
1946
1983
  ext = rb_const_get_at(mimic, rb_intern("Ext"));
@@ -1966,8 +2003,6 @@ define_mimic_json(int argc, VALUE *argv, VALUE self) {
1966
2003
  rb_funcall2(Oj, rb_intern("mimic_loaded"), 0, 0);
1967
2004
  }
1968
2005
  }
1969
- dummy = rb_gv_get("$VERBOSE");
1970
- rb_gv_set("$VERBOSE", Qfalse);
1971
2006
  rb_define_module_function(mimic, "parser=", no_op1, 1);
1972
2007
  rb_define_module_function(mimic, "generator=", no_op1, 1);
1973
2008
  rb_define_module_function(mimic, "create_id=", mimic_create_id, 1);
@@ -1991,7 +2026,7 @@ define_mimic_json(int argc, VALUE *argv, VALUE self) {
1991
2026
 
1992
2027
  rb_define_method(rb_cObject, "to_json", mimic_object_to_json, -1);
1993
2028
 
1994
- rb_gv_set("$VERBOSE", dummy);
2029
+ rb_gv_set("$VERBOSE", verbose);
1995
2030
 
1996
2031
  create_additions_sym = ID2SYM(rb_intern("create_additions")); rb_gc_register_address(&create_additions_sym);
1997
2032
  symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
@@ -2186,6 +2221,7 @@ void Init_oj() {
2186
2221
  escape_mode_sym = ID2SYM(rb_intern("escape_mode")); rb_gc_register_address(&escape_mode_sym);
2187
2222
  float_prec_sym = ID2SYM(rb_intern("float_precision"));rb_gc_register_address(&float_prec_sym);
2188
2223
  float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
2224
+ hash_class_sym = ID2SYM(rb_intern("hash_class")); rb_gc_register_address(&hash_class_sym);
2189
2225
  huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
2190
2226
  indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&indent_sym);
2191
2227
  json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
@@ -2196,6 +2232,7 @@ void Init_oj() {
2196
2232
  null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
2197
2233
  object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&object_nl_sym);
2198
2234
  object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
2235
+ omit_nil_sym = ID2SYM(rb_intern("omit_nil")); rb_gc_register_address(&omit_nil_sym);
2199
2236
  quirks_mode_sym = ID2SYM(rb_intern("quirks_mode")); rb_gc_register_address(&quirks_mode_sym);
2200
2237
  allow_invalid_unicode_sym = ID2SYM(rb_intern("allow_invalid_unicode"));rb_gc_register_address(&allow_invalid_unicode_sym);
2201
2238
  raise_sym = ID2SYM(rb_intern("raise")); rb_gc_register_address(&raise_sym);
@@ -139,6 +139,7 @@ typedef struct _DumpOpts {
139
139
  uint8_t hash_size;
140
140
  uint8_t array_size;
141
141
  char nan_dump; // NanDump
142
+ bool omit_nil;
142
143
  } *DumpOpts;
143
144
 
144
145
  typedef struct _Options {
@@ -162,6 +163,7 @@ typedef struct _Options {
162
163
  int sec_prec; // second precision when dumping time
163
164
  char float_prec; // float precision, linked to float_fmt
164
165
  char float_fmt[7]; // float format for dumping, if empty use Ruby
166
+ VALUE hash_class; // class to use in place of Hash on load
165
167
  struct _DumpOpts dump_opts;
166
168
  } *Options;
167
169
 
@@ -176,6 +178,7 @@ typedef struct _Out {
176
178
  Options opts;
177
179
  uint32_t hash_cnt;
178
180
  int allocated;
181
+ bool omit_nil;
179
182
  } *Out;
180
183
 
181
184
  typedef struct _StrWriter {
@@ -42,11 +42,6 @@
42
42
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
43
43
  #define OJ_INFINITY (1.0/0.0)
44
44
 
45
- #ifdef RUBINIUS_RUBY
46
- #define NUM_MAX 0x07FFFFFF
47
- #else
48
- #define NUM_MAX (FIXNUM_MAX >> 8)
49
- #endif
50
45
  //#define EXP_MAX 1023
51
46
  #define EXP_MAX 100000
52
47
  #define DEC_MAX 15
@@ -436,9 +431,7 @@ read_num(ParseInfo pi) {
436
431
  if (0 < ni.i) {
437
432
  dec_cnt++;
438
433
  }
439
- if (ni.big) {
440
- ni.big++;
441
- } else {
434
+ if (!ni.big) {
442
435
  int d = (*pi->cur - '0');
443
436
 
444
437
  ni.i = ni.i * 10 + d;
@@ -452,7 +445,7 @@ read_num(ParseInfo pi) {
452
445
  for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
453
446
  int d = (*pi->cur - '0');
454
447
 
455
- if (0 < ni.num) {
448
+ if (0 < ni.num || 0 < ni.i) {
456
449
  dec_cnt++;
457
450
  }
458
451
  ni.num = ni.num * 10 + d;
@@ -456,7 +456,7 @@ read_num(ParseInfo pi) {
456
456
  for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
457
457
  int d = (c - '0');
458
458
 
459
- if (0 < ni.num) {
459
+ if (0 < ni.num || 0 < ni.i) {
460
460
  dec_cnt++;
461
461
  }
462
462
  ni.num = ni.num * 10 + d;
@@ -70,6 +70,9 @@ add_num(ParseInfo pi, NumInfo ni) {
70
70
 
71
71
  static VALUE
72
72
  start_hash(ParseInfo pi) {
73
+ if (Qnil != pi->options.hash_class) {
74
+ return rb_class_new_instance(0, NULL, pi->options.hash_class);
75
+ }
73
76
  return rb_hash_new();
74
77
  }
75
78
 
data/lib/oj.rb CHANGED
@@ -34,6 +34,7 @@ end
34
34
 
35
35
  require 'oj/version'
36
36
  require 'oj/bag'
37
+ require 'oj/easy_hash'
37
38
  require 'oj/error'
38
39
  require 'oj/mimic'
39
40
  require 'oj/saj'
@@ -0,0 +1,44 @@
1
+
2
+ module Oj
3
+
4
+ # A Hash subclass that normalizes the hash keys to allow lookup by the
5
+ # key.to_s or key.to_sym. It also supports looking up hash values by methods
6
+ # that match the keys.
7
+ class EasyHash < Hash
8
+
9
+ # Initializes the instance to an empty Hash.
10
+ def initialize()
11
+ end
12
+
13
+ # Replaces the Object.respond_to?() method.
14
+ # @param [Symbol] m method symbol
15
+ # @return [Boolean] true for any method that matches an instance
16
+ # variable reader, otherwise false.
17
+ def respond_to?(m)
18
+ return true if super
19
+ return true if has_key?(key)
20
+ return true if has_key?(key.to_s)
21
+ has_key?(key.to_sym)
22
+ end
23
+
24
+ def [](key)
25
+ return fetch(key, nil) if has_key?(key)
26
+ return fetch(key.to_s, nil) if has_key?(key.to_s)
27
+ fetch(key.to_sym, nil)
28
+ end
29
+
30
+ # Handles requests for Hash values. Others cause an Exception to be raised.
31
+ # @param [Symbol|String] m method symbol
32
+ # @return [Boolean] the value of the specified instance variable.
33
+ # @raise [ArgumentError] if an argument is given. Zero arguments expected.
34
+ # @raise [NoMethodError] if the instance variable is not defined.
35
+ def method_missing(m, *args, &block)
36
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
37
+ return fetch(m, nil) if has_key?(m)
38
+ return fetch(m.to_s, nil) if has_key?(m.to_s)
39
+ return fetch(m.to_sym, nil) if has_key?(m.to_sym)
40
+ raise NoMethodError.new("undefined method #{m}", m)
41
+ end
42
+
43
+ end # EasyHash
44
+ end # Oj
@@ -4,9 +4,11 @@ module Oj
4
4
  def self.mimic_loaded(mimic_paths=[])
5
5
  $LOAD_PATH.each do |d|
6
6
  next unless File.exist?(d)
7
- offset = d.size() + 1
8
- Dir.glob(File.join(d, '**', '*.rb')).each do |file|
9
- next if file[offset..-1] !~ /^json[\/\\\.]{1}/
7
+
8
+ jfile = File.join(d, 'json.rb')
9
+ $LOADED_FEATURES << jfile unless $LOADED_FEATURES.include?(jfile) if File.exist?(jfile)
10
+
11
+ Dir.glob(File.join(d, 'json', '**', '*.rb')).each do |file|
10
12
  $LOADED_FEATURES << file unless $LOADED_FEATURES.include?(file)
11
13
  end
12
14
  end
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '2.16.1'
4
+ VERSION = '2.17.0'
5
5
  end
@@ -107,7 +107,7 @@ class SharedMimicTest < Minitest::Test
107
107
  end
108
108
 
109
109
  def test_load_proc
110
- Oj.mimic_JSON # TBD
110
+ Oj.mimic_JSON
111
111
  children = []
112
112
  json = %{{"a":1,"b":[true,false]}}
113
113
  if 'rubinius' == $ruby || '1.8.7' == RUBY_VERSION
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << File.join(File.dirname(__FILE__), '..')
5
+
6
+ require 'helper'
7
+ require 'oj/active_support_helper'
8
+
9
+ class ObjectFolder < Minitest::Test
10
+ def setup
11
+ @default_options = Oj.default_options
12
+ end
13
+
14
+ def teardown
15
+ Oj.default_options = @default_options
16
+ end
17
+
18
+ def test_as_json
19
+ Oj.mimic_JSON()
20
+ dt = DateTime.now()
21
+
22
+ json = dt.to_json()
23
+
24
+ puts json
25
+ end
26
+
27
+ end
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+
6
+ require 'helper'
7
+
8
+ class Hashi < Minitest::Test
9
+
10
+ module TestModule
11
+ end
12
+
13
+ def test_dump
14
+ h = Oj::EasyHash.new()
15
+ h['abc'] = 3
16
+ out = Oj.dump(h, :mode => :compat)
17
+ assert_equal(%|{"abc":3}|, out)
18
+ end
19
+
20
+ def test_load
21
+ obj = Oj.load(%|{"abc":3}|, :mode => :compat, :hash_class => Oj::EasyHash)
22
+
23
+ assert_equal(Oj::EasyHash, obj.class)
24
+ assert_equal(3, obj['abc'])
25
+ assert_equal(3, obj[:abc])
26
+ assert_equal(3, obj.abc())
27
+ end
28
+
29
+ end # HashTest
@@ -141,6 +141,8 @@ class Juice < Minitest::Test
141
141
  :object_nl=>'o',
142
142
  :space_before=>'b',
143
143
  :nan=>:huge,
144
+ :hash_class=>Hash,
145
+ :omit_nil=>false,
144
146
  }
145
147
  Oj.default_options = alt
146
148
  opts = Oj.default_options()
@@ -172,7 +174,8 @@ class Juice < Minitest::Test
172
174
  end
173
175
 
174
176
  def test_float_parse
175
- Oj.default_options = { :float_precision => 16 }
177
+ Oj.default_options = { :float_precision => 16, :bigdecimal_load => :auto }
178
+ =begin
176
179
  n = Oj.load('0.00001234567890123456')
177
180
  assert_equal(Float, n.class)
178
181
  assert_equal('1.234567890123456e-05', "%0.15e" % [n])
@@ -180,14 +183,15 @@ class Juice < Minitest::Test
180
183
  n = Oj.load('-0.00001234567890123456')
181
184
  assert_equal(Float, n.class)
182
185
  assert_equal('-1.234567890123456e-05', "%0.15e" % [n])
183
-
186
+ =end
184
187
  n = Oj.load('1000.0000123456789')
185
188
  assert_equal(BigDecimal, n.class)
186
189
  assert_equal('0.10000000123456789E4', n.to_s)
187
-
190
+ =begin
188
191
  n = Oj.load('-0.000012345678901234567')
189
192
  assert_equal(BigDecimal, n.class)
190
193
  assert_equal('-0.12345678901234567E-4', n.to_s)
194
+ =end
191
195
  end
192
196
 
193
197
  def test_float_dump
@@ -1327,6 +1331,22 @@ class Juice < Minitest::Test
1327
1331
  assert_equal({}, Oj.load("{}", :quirks_mode => true))
1328
1332
  end
1329
1333
 
1334
+ def test_omit_nil
1335
+ jam = Jam.new({'a' => 1, 'b' => nil }, nil)
1336
+
1337
+ json = Oj.dump(jam, :omit_nil => true, :mode => :object)
1338
+ assert_equal(%|{"^o":"Juice::Jam","x":{"a":1}}|, json)
1339
+
1340
+ json = Oj.dump(jam, :omit_nil => true, :mode => :compat)
1341
+ assert_equal(%|{"x":{"a":1}}|, json)
1342
+
1343
+ json = Oj.dump({'x' => {'a' => 1, 'b' => nil }, 'y' => nil}, :omit_nil => true, :mode => :strict)
1344
+ assert_equal(%|{"x":{"a":1}}|, json)
1345
+
1346
+ json = Oj.dump({'x' => {'a' => 1, 'b' => nil }, 'y' => nil}, :omit_nil => true, :mode => :null)
1347
+ assert_equal(%|{"x":{"a":1}}|, json)
1348
+ end
1349
+
1330
1350
  def dump_and_load(obj, trace=false)
1331
1351
  json = Oj.dump(obj, :indent => 2)
1332
1352
  puts json if trace
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oj
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.16.1
4
+ version: 2.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-21 00:00:00.000000000 Z
11
+ date: 2016-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -97,6 +97,7 @@ files:
97
97
  - lib/oj.rb
98
98
  - lib/oj/active_support_helper.rb
99
99
  - lib/oj/bag.rb
100
+ - lib/oj/easy_hash.rb
100
101
  - lib/oj/error.rb
101
102
  - lib/oj/mimic.rb
102
103
  - lib/oj/saj.rb
@@ -123,6 +124,7 @@ files:
123
124
  - test/isolated/test_mimic_define.rb
124
125
  - test/isolated/test_mimic_rails_after.rb
125
126
  - test/isolated/test_mimic_rails_before.rb
127
+ - test/isolated/test_mimic_rails_datetime.rb
126
128
  - test/mod.rb
127
129
  - test/perf.rb
128
130
  - test/perf_compat.rb
@@ -154,6 +156,7 @@ files:
154
156
  - test/test_fast.rb
155
157
  - test/test_file.rb
156
158
  - test/test_gc.rb
159
+ - test/test_hash.rb
157
160
  - test/test_object.rb
158
161
  - test/test_saj.rb
159
162
  - test/test_scp.rb
@@ -210,6 +213,7 @@ test_files:
210
213
  - test/isolated/test_mimic_define.rb
211
214
  - test/isolated/test_mimic_rails_after.rb
212
215
  - test/isolated/test_mimic_rails_before.rb
216
+ - test/isolated/test_mimic_rails_datetime.rb
213
217
  - test/mod.rb
214
218
  - test/perf.rb
215
219
  - test/perf_compat.rb
@@ -241,6 +245,7 @@ test_files:
241
245
  - test/test_fast.rb
242
246
  - test/test_file.rb
243
247
  - test/test_gc.rb
248
+ - test/test_hash.rb
244
249
  - test/test_object.rb
245
250
  - test/test_saj.rb
246
251
  - test/test_scp.rb