oj 3.8.1 → 3.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/oj/compat.c +5 -5
  4. data/ext/oj/custom.c +65 -38
  5. data/ext/oj/dump.c +9 -12
  6. data/ext/oj/dump_compat.c +8 -10
  7. data/ext/oj/dump_object.c +18 -11
  8. data/ext/oj/dump_strict.c +6 -5
  9. data/ext/oj/extconf.rb +6 -0
  10. data/ext/oj/mimic_json.c +15 -3
  11. data/ext/oj/object.c +8 -5
  12. data/ext/oj/oj.c +50 -31
  13. data/ext/oj/oj.h +6 -4
  14. data/ext/oj/parse.c +16 -3
  15. data/ext/oj/parse.h +1 -0
  16. data/ext/oj/rails.c +40 -4
  17. data/ext/oj/resolve.c +3 -3
  18. data/ext/oj/sparse.c +5 -0
  19. data/ext/oj/util.c +5 -5
  20. data/ext/oj/val_stack.c +9 -9
  21. data/ext/oj/val_stack.h +9 -9
  22. data/ext/oj/wab.c +9 -9
  23. data/lib/oj/version.rb +1 -1
  24. data/pages/Options.md +4 -0
  25. data/pages/Rails.md +21 -21
  26. data/test/activesupport5/abstract_unit.rb +45 -0
  27. data/test/activesupport5/decoding_test.rb +68 -60
  28. data/test/activesupport5/encoding_test.rb +111 -96
  29. data/test/activesupport5/encoding_test_cases.rb +33 -25
  30. data/test/activesupport5/test_helper.rb +43 -21
  31. data/test/activesupport5/time_zone_test_helpers.rb +18 -3
  32. data/test/activesupport6/abstract_unit.rb +44 -0
  33. data/test/activesupport6/decoding_test.rb +133 -0
  34. data/test/activesupport6/encoding_test.rb +507 -0
  35. data/test/activesupport6/encoding_test_cases.rb +98 -0
  36. data/test/activesupport6/test_common.rb +17 -0
  37. data/test/activesupport6/test_helper.rb +163 -0
  38. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  39. data/test/bar.rb +8 -11
  40. data/test/baz.rb +16 -0
  41. data/test/foo.rb +42 -157
  42. data/test/test_compat.rb +0 -7
  43. data/test/test_custom.rb +25 -6
  44. data/test/test_integer_range.rb +1 -2
  45. data/test/test_object.rb +4 -3
  46. data/test/test_rails.rb +26 -0
  47. data/test/test_strict.rb +24 -1
  48. data/test/test_various.rb +41 -62
  49. data/test/tests.rb +1 -0
  50. metadata +22 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e31b61d33e83ce9e5e20148749717af84c4cc9f02a6faeb14383f7243095439
4
- data.tar.gz: 700b0823f12722d2dd2028875abd2bf624a85422b42b5a1251632f63069358f5
3
+ metadata.gz: 3dd1cae4ccf720f35b777913213b66466c7d9752055c60d828cdf681956731a3
4
+ data.tar.gz: e913c57a4619bfbea97144f6f4783219aca294e598c8c6449ddfc6cb997b46f7
5
5
  SHA512:
6
- metadata.gz: 5daaaf6c3ac308e2cdca660804fc4ff2d87b1c724e49e3fd0a36bd223c7c2f64d0764d60a3d51d242ac4da370488d0f78db42214527f17afcccd9e950dc540c9
7
- data.tar.gz: dd9d68dd43f073af2c16a87ac4725beff0592d1410296dbc06c862785a25f73ba1a4085beff9e2ecf73e7e5908f69f9de7be1ac3be9b725a99804db42130de17
6
+ metadata.gz: dc0b7bd0e9ea90e69eda6a6205c09540e2217f9ccdcb3c6e937fb82e4b979fada30a028b64559ac5dfddc22afb9d4302669de35315bb5c5392ad100a373bb472
7
+ data.tar.gz: 8d8ad9eeb68fb2d058c3f499ad51fc8c50d3349b36a237769f996a43de58449fbae36d3bff82c6be6a16828331f12aa19df6a1ef90b5bdff78ecdf732450a268
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # [![{}j](http://www.ohler.com/dev/images/oj_comet_64.svg)](http://www.ohler.com/oj) gem
2
2
 
3
- [![Build Status](https://img.shields.io/travis/ohler55/oj/master.svg)](http://travis-ci.org/ohler55/oj?branch=master) [![AppVeyor](https://img.shields.io/appveyor/ci/ohler55/oj/master.svg)](https://ci.appveyor.com/project/ohler55/oj) ![Gem](https://img.shields.io/gem/v/oj.svg) ![Gem](https://img.shields.io/gem/dt/oj.svg) [![SemVer compatibility](https://api.dependabot.com/badges/compatibility_score?dependency-name=oj&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver) [![TideLift](https://tidelift.com/badges/github/ohler55/oj)](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
3
+ [![Build Status](https://img.shields.io/travis/ohler55/oj/master.svg?logo=travis)](http://travis-ci.org/ohler55/oj?branch=master) [![AppVeyor](https://img.shields.io/appveyor/ci/ohler55/oj/master.svg?logo=appveyor)](https://ci.appveyor.com/project/ohler55/oj) ![Gem](https://img.shields.io/gem/v/oj.svg) ![Gem](https://img.shields.io/gem/dt/oj.svg) [![SemVer compatibility](https://api.dependabot.com/badges/compatibility_score?dependency-name=oj&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver) [![TideLift](https://tidelift.com/badges/github/ohler55/oj)](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
4
4
 
5
5
  A *fast* JSON parser and Object marshaller as a Ruby gem.
6
6
 
@@ -42,7 +42,7 @@ gem 'oj'
42
42
 
43
43
  ## Support
44
44
 
45
- [Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
45
+ [Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme) Security updates are [supported](https://tidelift.com/security).
46
46
 
47
47
  ## Further Reading
48
48
 
@@ -65,7 +65,7 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
65
65
  static VALUE
66
66
  start_hash(ParseInfo pi) {
67
67
  volatile VALUE h;
68
-
68
+
69
69
  if (Qnil != pi->options.hash_class) {
70
70
  h = rb_class_new_instance(0, NULL, pi->options.hash_class);
71
71
  } else {
@@ -87,7 +87,7 @@ end_hash(struct _parseInfo *pi) {
87
87
  clas = oj_name2class(pi, parent->classname, parent->clen, 0, rb_eArgError);
88
88
  if (Qundef != clas) { // else an error
89
89
  ID creatable = rb_intern("json_creatable?");
90
-
90
+
91
91
  if (!rb_respond_to(clas, creatable) || Qtrue == rb_funcall(clas, creatable, 0)) {
92
92
  parent->val = rb_funcall(clas, oj_json_create_id, 1, parent->val);
93
93
  }
@@ -146,7 +146,7 @@ add_num(ParseInfo pi, NumInfo ni) {
146
146
  static void
147
147
  hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
148
148
  volatile VALUE rval = oj_num_as_value(ni);
149
-
149
+
150
150
  if (!oj_use_hash_alt && rb_cHash != rb_obj_class(parent->val)) {
151
151
  // The rb_hash_set would still work but the unit tests for the
152
152
  // json gem require the less efficient []= method be called to set
@@ -192,7 +192,7 @@ static void
192
192
  array_append_num(ParseInfo pi, NumInfo ni) {
193
193
  Val parent = stack_peek(&pi->stack);
194
194
  volatile VALUE rval = oj_num_as_value(ni);
195
-
195
+
196
196
  if (!oj_use_array_alt && rb_cArray != rb_obj_class(parent->val)) {
197
197
  // The rb_ary_push would still work but the unit tests for the json
198
198
  // gem require the less efficient << method be called to push the
@@ -274,7 +274,7 @@ oj_compat_load(int argc, VALUE *argv, VALUE self) {
274
274
  pi.options.nilnil = Yes;
275
275
  pi.options.empty_string = Yes;
276
276
  oj_set_compat_callbacks(&pi);
277
-
277
+
278
278
  if (T_STRING == rb_type(*argv)) {
279
279
  return oj_pi_parse(argc, argv, &pi, 0, 0, false);
280
280
  } else {
@@ -32,6 +32,13 @@ dump_obj_str(VALUE obj, int depth, Out out) {
32
32
  oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
33
33
  }
34
34
 
35
+ static void
36
+ dump_obj_as_str(VALUE obj, int depth, Out out) {
37
+ volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
38
+ const char *str = rb_string_value_ptr((VALUE*)&rstr);
39
+
40
+ oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
41
+ }
35
42
 
36
43
  static void
37
44
  bigdecimal_dump(VALUE obj, int depth, Out out) {
@@ -57,19 +64,23 @@ static ID imag_id = 0;
57
64
 
58
65
  static void
59
66
  complex_dump(VALUE obj, int depth, Out out) {
60
- struct _attr attrs[] = {
61
- { "real", 4, Qnil },
62
- { "imag", 4, Qnil },
63
- { NULL, 0, Qnil },
64
- };
65
- if (0 == real_id) {
66
- real_id = rb_intern("real");
67
- imag_id = rb_intern("imag");
68
- }
69
- attrs[0].value = rb_funcall(obj, real_id, 0);
70
- attrs[1].value = rb_funcall(obj, imag_id, 0);
67
+ if (NULL != out->opts->create_id) {
68
+ struct _attr attrs[] = {
69
+ { "real", 4, Qnil },
70
+ { "imag", 4, Qnil },
71
+ { NULL, 0, Qnil },
72
+ };
73
+ if (0 == real_id) {
74
+ real_id = rb_intern("real");
75
+ imag_id = rb_intern("imag");
76
+ }
77
+ attrs[0].value = rb_funcall(obj, real_id, 0);
78
+ attrs[1].value = rb_funcall(obj, imag_id, 0);
71
79
 
72
- oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
80
+ oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
81
+ } else {
82
+ dump_obj_as_str(obj, depth, out);
83
+ }
73
84
  }
74
85
 
75
86
  static VALUE
@@ -193,17 +204,21 @@ openstruct_load(VALUE clas, VALUE args) {
193
204
 
194
205
  static void
195
206
  range_dump(VALUE obj, int depth, Out out) {
196
- struct _attr attrs[] = {
197
- { "begin", 5, Qnil },
198
- { "end", 3, Qnil },
199
- { "exclude", 7, Qnil },
200
- { NULL, 0, Qnil },
201
- };
202
- attrs[0].value = rb_funcall(obj, oj_begin_id, 0);
203
- attrs[1].value = rb_funcall(obj, oj_end_id, 0);
204
- attrs[2].value = rb_funcall(obj, oj_exclude_end_id, 0);
207
+ if (NULL != out->opts->create_id) {
208
+ struct _attr attrs[] = {
209
+ { "begin", 5, Qnil },
210
+ { "end", 3, Qnil },
211
+ { "exclude", 7, Qnil },
212
+ { NULL, 0, Qnil },
213
+ };
214
+ attrs[0].value = rb_funcall(obj, oj_begin_id, 0);
215
+ attrs[1].value = rb_funcall(obj, oj_end_id, 0);
216
+ attrs[2].value = rb_funcall(obj, oj_exclude_end_id, 0);
205
217
 
206
- oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
218
+ oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
219
+ } else {
220
+ dump_obj_as_str(obj, depth, out);
221
+ }
207
222
  }
208
223
 
209
224
  static VALUE
@@ -222,19 +237,23 @@ static ID denominator_id = 0;
222
237
 
223
238
  static void
224
239
  rational_dump(VALUE obj, int depth, Out out) {
225
- struct _attr attrs[] = {
226
- { "numerator", 9, Qnil },
227
- { "denominator", 11, Qnil },
228
- { NULL, 0, Qnil },
229
- };
230
- if (0 == numerator_id) {
231
- numerator_id = rb_intern("numerator");
232
- denominator_id = rb_intern("denominator");
233
- }
234
- attrs[0].value = rb_funcall(obj, numerator_id, 0);
235
- attrs[1].value = rb_funcall(obj, denominator_id, 0);
240
+ if (NULL != out->opts->create_id) {
241
+ struct _attr attrs[] = {
242
+ { "numerator", 9, Qnil },
243
+ { "denominator", 11, Qnil },
244
+ { NULL, 0, Qnil },
245
+ };
246
+ if (0 == numerator_id) {
247
+ numerator_id = rb_intern("numerator");
248
+ denominator_id = rb_intern("denominator");
249
+ }
250
+ attrs[0].value = rb_funcall(obj, numerator_id, 0);
251
+ attrs[1].value = rb_funcall(obj, denominator_id, 0);
236
252
 
237
- oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
253
+ oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
254
+ } else {
255
+ dump_obj_as_str(obj, depth, out);
256
+ }
238
257
  }
239
258
 
240
259
  static VALUE
@@ -278,7 +297,8 @@ static struct _code codes[] = {
278
297
  };
279
298
 
280
299
  static int
281
- hash_cb(VALUE key, VALUE value, Out out) {
300
+ hash_cb(VALUE key, VALUE value, VALUE ov) {
301
+ Out out = (Out)ov;
282
302
  int depth = out->depth;
283
303
 
284
304
  if (oj_dump_ignore(out->opts, value)) {
@@ -573,7 +593,8 @@ dump_common(VALUE obj, int depth, Out out) {
573
593
  }
574
594
 
575
595
  static int
576
- dump_attr_cb(ID key, VALUE value, Out out) {
596
+ dump_attr_cb(ID key, VALUE value, VALUE ov) {
597
+ Out out = (Out)ov;
577
598
  int depth = out->depth;
578
599
  size_t size;
579
600
  const char *attr;
@@ -590,6 +611,8 @@ dump_attr_cb(ID key, VALUE value, Out out) {
590
611
  // the key name is NULL. Not an empty string but NULL.
591
612
  if (NULL == attr) {
592
613
  attr = "";
614
+ } else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
615
+ return ST_CONTINUE;
593
616
  }
594
617
  if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
595
618
  return ST_CONTINUE;
@@ -874,7 +897,11 @@ dump_data(VALUE obj, int depth, Out out, bool as_ok) {
874
897
 
875
898
  static void
876
899
  dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
877
- dump_obj_str(obj, depth, out);
900
+ if (NULL != out->opts->create_id) {
901
+ dump_obj_str(obj, depth, out);
902
+ } else {
903
+ dump_obj_as_str(obj, depth, out);
904
+ }
878
905
  }
879
906
 
880
907
  static void
@@ -1046,7 +1073,7 @@ hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
1046
1073
  oj_set_obj_ivar(parent, kval, rval);
1047
1074
  break;
1048
1075
  case T_HASH:
1049
- if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 == strncmp("time", parent->key, 4)) {
1076
+ if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 != ni->div && 0 == strncmp("time", parent->key, 4)) {
1050
1077
  int64_t nsec = ni->num * 1000000000LL / ni->div;
1051
1078
 
1052
1079
  if (ni->neg) {
@@ -548,7 +548,7 @@ oj_dump_xml_time(VALUE obj, Out out) {
548
548
  tzhour = (int)(tzsecs / 3600);
549
549
  tzmin = (int)(tzsecs / 60) - (tzhour * 60);
550
550
  }
551
- if (0 == nsec || 0 == out->opts->sec_prec) {
551
+ if ((0 == nsec && !out->opts->sec_prec_set) || 0 == out->opts->sec_prec) {
552
552
  if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
553
553
  sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
554
554
  oj_dump_cstr(buf, 20, 0, 0, out);
@@ -1023,8 +1023,8 @@ oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
1023
1023
  int neg = 0;
1024
1024
  bool dump_as_string = false;
1025
1025
 
1026
- if (out->opts->integer_range_max != 0 && out->opts->integer_range_min != 0 &&
1027
- (out->opts->integer_range_max < num || out->opts->integer_range_min > num)) {
1026
+ if (out->opts->int_range_max != 0 && out->opts->int_range_min != 0 &&
1027
+ (out->opts->int_range_max < num || out->opts->int_range_min > num)) {
1028
1028
  dump_as_string = true;
1029
1029
  }
1030
1030
  if (0 > num) {
@@ -1062,23 +1062,20 @@ void
1062
1062
  oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
1063
1063
  volatile VALUE rs = rb_big2str(obj, 10);
1064
1064
  int cnt = (int)RSTRING_LEN(rs);
1065
- bool dump_as_string = false;
1065
+ bool dump_as_string = false;
1066
1066
 
1067
- if (out->opts->integer_range_max != 0 || out->opts->integer_range_min != 0) { // Bignum cannot be inside of Fixnum range
1067
+ if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) { // Bignum cannot be inside of Fixnum range
1068
1068
  dump_as_string = true;
1069
1069
  assure_size(out, cnt + 2);
1070
1070
  *out->cur++ = '"';
1071
- } else {
1071
+ } else {
1072
1072
  assure_size(out, cnt);
1073
- }
1074
-
1073
+ }
1075
1074
  memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
1076
1075
  out->cur += cnt;
1077
-
1078
- if(dump_as_string) {
1076
+ if (dump_as_string) {
1079
1077
  *out->cur++ = '"';
1080
- }
1081
-
1078
+ }
1082
1079
  *out->cur = '\0';
1083
1080
  }
1084
1081
 
@@ -648,7 +648,8 @@ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
648
648
  }
649
649
 
650
650
  static int
651
- hash_cb(VALUE key, VALUE value, Out out) {
651
+ hash_cb(VALUE key, VALUE value, VALUE ov) {
652
+ Out out = (Out)ov;
652
653
  int depth = out->depth;
653
654
 
654
655
  if (out->omit_nil && Qnil == value) {
@@ -870,7 +871,7 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
870
871
  // this must use to_s to pass the json gem unit tests.
871
872
  volatile VALUE rs;
872
873
  int cnt;
873
- bool dump_as_string = false;
874
+ bool dump_as_string = false;
874
875
 
875
876
  if (use_bignum_alt) {
876
877
  rs = rb_big2str(obj, 10);
@@ -880,21 +881,18 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
880
881
  rb_check_type(rs, T_STRING);
881
882
  cnt = (int)RSTRING_LEN(rs);
882
883
 
883
- if (out->opts->integer_range_min != 0 || out->opts->integer_range_max != 0) {
884
+ if (out->opts->int_range_min != 0 || out->opts->int_range_max != 0) {
884
885
  dump_as_string = true; // Bignum cannot be inside of Fixnum range
885
886
  assure_size(out, cnt + 2);
886
887
  *out->cur++ = '"';
887
- } else {
888
+ } else {
888
889
  assure_size(out, cnt);
889
- }
890
-
890
+ }
891
891
  memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
892
892
  out->cur += cnt;
893
-
894
- if(dump_as_string) {
893
+ if (dump_as_string) {
895
894
  *out->cur++ = '"';
896
- }
897
-
895
+ }
898
896
  *out->cur = '\0';
899
897
  }
900
898
 
@@ -56,7 +56,7 @@ dump_data(VALUE obj, int depth, Out out, bool as_ok) {
56
56
  }
57
57
  } else {
58
58
  long id = oj_check_circular(obj, out);
59
-
59
+
60
60
  if (0 <= id) {
61
61
  dump_obj_attrs(obj, clas, id, depth, out);
62
62
  }
@@ -72,7 +72,7 @@ dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
72
72
  volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
73
73
  const char *str = rb_string_value_ptr((VALUE*)&rstr);
74
74
  int len = (int)RSTRING_LEN(rstr);
75
-
75
+
76
76
  if (0 == strcasecmp("Infinity", str)) {
77
77
  str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
78
78
  oj_dump_raw(str, len, out);
@@ -224,7 +224,8 @@ dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
224
224
  }
225
225
 
226
226
  static int
227
- hash_cb(VALUE key, VALUE value, Out out) {
227
+ hash_cb(VALUE key, VALUE value, VALUE ov) {
228
+ Out out = (Out)ov;
228
229
  int depth = out->depth;
229
230
  long size = depth * out->indent + 1;
230
231
 
@@ -280,7 +281,7 @@ hash_cb(VALUE key, VALUE value, Out out) {
280
281
  }
281
282
  out->depth = depth;
282
283
  *out->cur++ = ',';
283
-
284
+
284
285
  return ST_CONTINUE;
285
286
  }
286
287
 
@@ -348,7 +349,8 @@ dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
348
349
 
349
350
  #ifdef HAVE_RB_IVAR_FOREACH
350
351
  static int
351
- dump_attr_cb(ID key, VALUE value, Out out) {
352
+ dump_attr_cb(ID key, VALUE value, VALUE ov) {
353
+ Out out = (Out)ov;
352
354
  int depth = out->depth;
353
355
  size_t size = depth * out->indent + 1;
354
356
  const char *attr = rb_id2name(key);
@@ -363,6 +365,8 @@ dump_attr_cb(ID key, VALUE value, Out out) {
363
365
  // the key name is NULL. Not an empty string but NULL.
364
366
  if (NULL == attr) {
365
367
  attr = "";
368
+ } else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
369
+ return ST_CONTINUE;
366
370
  }
367
371
  if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
368
372
  return ST_CONTINUE;
@@ -384,7 +388,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
384
388
  oj_dump_obj_val(value, depth, out);
385
389
  out->depth = depth;
386
390
  *out->cur++ = ',';
387
-
391
+
388
392
  return ST_CONTINUE;
389
393
  }
390
394
  #endif
@@ -424,7 +428,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
424
428
  v = rb_funcall(obj, *odd->attrs, 0);
425
429
  if (Qundef == v || T_STRING != rb_type(v)) {
426
430
  rb_raise(rb_eEncodingError, "Invalid type for raw JSON.");
427
- } else {
431
+ } else {
428
432
  const char *s = rb_string_value_ptr((VALUE*)&v);
429
433
  int len = (int)RSTRING_LEN(v);
430
434
  const char *name = rb_id2name(*odd->attrs);
@@ -460,7 +464,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
460
464
  char *n;
461
465
  char *end;
462
466
  ID i;
463
-
467
+
464
468
  if (sizeof(nbuf) <= nlen) {
465
469
  if (NULL == (n2 = strdup(name))) {
466
470
  rb_raise(rb_eNoMemError, "for attribute name.");
@@ -610,9 +614,12 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
610
614
  size = d2 * out->indent + 1;
611
615
  for (i = cnt; 0 < i; i--, np++) {
612
616
  VALUE value;
613
-
617
+
614
618
  vid = rb_to_id(*np);
615
619
  attr = rb_id2name(vid);
620
+ if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
621
+ return ST_CONTINUE;
622
+ }
616
623
  value = rb_ivar_get(obj, vid);
617
624
 
618
625
  if (oj_dump_ignore(out->opts, value)) {
@@ -739,7 +746,7 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
739
746
  #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
740
747
  cnt = (int)RSTRUCT_LEN(obj);
741
748
  #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
742
-
749
+
743
750
  for (i = 0; i < cnt; i++) {
744
751
  v = RSTRUCT_GET(obj, i);
745
752
  if (oj_dump_ignore(out->opts, v)) {
@@ -812,7 +819,7 @@ static DumpFunc obj_funcs[] = {
812
819
  void
813
820
  oj_dump_obj_val(VALUE obj, int depth, Out out) {
814
821
  int type = rb_type(obj);
815
-
822
+
816
823
  if (Yes == out->opts->trace) {
817
824
  oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
818
825
  }
@@ -45,7 +45,7 @@ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
45
45
  cnt = 3;
46
46
  } else {
47
47
  NanDump nd = out->opts->dump_opts.nan_dump;
48
-
48
+
49
49
  if (AutoNan == nd) {
50
50
  nd = RaiseNan;
51
51
  }
@@ -195,11 +195,12 @@ dump_array(VALUE a, int depth, Out out, bool as_ok) {
195
195
  }
196
196
 
197
197
  static int
198
- hash_cb(VALUE key, VALUE value, Out out) {
198
+ hash_cb(VALUE key, VALUE value, VALUE ov) {
199
+ Out out = (Out)ov;
199
200
  int depth = out->depth;
200
201
  long size;
201
202
  int rtype = rb_type(key);
202
-
203
+
203
204
  if (rtype != T_STRING && rtype != T_SYMBOL) {
204
205
  rb_raise(rb_eTypeError, "In :strict and :null mode all Hash keys must be Strings or Symbols, not %s.\n", rb_class2name(rb_obj_class(key)));
205
206
  }
@@ -359,7 +360,7 @@ static DumpFunc strict_funcs[] = {
359
360
  void
360
361
  oj_dump_strict_val(VALUE obj, int depth, Out out) {
361
362
  int type = rb_type(obj);
362
-
363
+
363
364
  if (Yes == out->opts->trace) {
364
365
  oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
365
366
  }
@@ -408,7 +409,7 @@ static DumpFunc null_funcs[] = {
408
409
  void
409
410
  oj_dump_null_val(VALUE obj, int depth, Out out) {
410
411
  int type = rb_type(obj);
411
-
412
+
412
413
  if (Yes == out->opts->trace) {
413
414
  oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
414
415
  }