oj 2.12.14 → 2.13.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 625b764edc8ea14b9f037b18d5f5981097345231
4
- data.tar.gz: 50d26c3238c9903708879f06ab25e5d9b94a2412
3
+ metadata.gz: bd957508587371c18e701b638fcf8191b3bc444d
4
+ data.tar.gz: aef52ecc143c4db76dfd1f9c64914a8a9021ad71
5
5
  SHA512:
6
- metadata.gz: 10576bbf301ba650159eff911f7ba48eb3bec46ddb760ff49486da282229c9cd911298f86326a0cfb1b25143ffdc360ba634eabb9eb5b4e053a4d663a478564a
7
- data.tar.gz: 8f96fe65d7c9c803957ae017a51d40e43cd186b1bad2473e8551cfdb68c06a91f2c3b3c62705f47f26f5b9cd58a06f9c9a01aeca8c0f9d06b75e52e735ca84a3
6
+ metadata.gz: 03d731a64121a180278f340025cb18e0644504ecb954a7a479a03f79fd6c46cd1ed00d48c850830433550ef968402f9f91a6903e888568075c3d38bb2626ed1d
7
+ data.tar.gz: 48f98ec630a2fe1f334de5eea37e952b549e7c97d98ab3f86e92a6608dd44e101da5fd853c3191ac76bf4e889609680ef5d97061330b67c7395e29a52cfae5d3
data/README.md CHANGED
@@ -26,11 +26,16 @@ Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announceme
26
26
 
27
27
  [![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](http://travis-ci.org/ohler55/oj)
28
28
 
29
- ## Release 2.12.14
29
+ ## Release 2.13.0
30
30
 
31
- - Change the failure mode for objects that can not be serialized such as a
32
- socket. Now in compat mode the to_s of the object is placed in the output
33
- instead of raising an exception.
31
+ - Oj no longer raises an exception if the to_hash method of an object does not
32
+ return a Hash. ActiveRecord has decided that to_hash should return an Array
33
+ instead so Oj now encodes what ever is returned.
34
+
35
+ - Added a register_odd_raw function that allows odd marshal functions to return
36
+ raw JSON as a string to be included in the dumped JSON.
37
+
38
+ - The register_odd function now supports modules in additions to classes.
34
39
 
35
40
  [Older release notes](http://www.ohler.com/dev/oj_misc/release_notes.html).
36
41
 
@@ -1249,7 +1249,12 @@ dump_data_comp(VALUE obj, int depth, Out out) {
1249
1249
  volatile VALUE h = rb_funcall(obj, oj_to_hash_id, 0);
1250
1250
 
1251
1251
  if (T_HASH != rb_type(h)) {
1252
- rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
1252
+ // It seems that ActiveRecord implemented to_hash so that it returns
1253
+ // an Array and not a Hash. To get around that any value returned
1254
+ // will be dumped.
1255
+
1256
+ //rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
1257
+ dump_val(h, depth, out, 0, 0);
1253
1258
  }
1254
1259
  dump_hash(h, Qundef, depth, out->opts->mode, out);
1255
1260
 
@@ -1354,7 +1359,12 @@ dump_obj_comp(VALUE obj, int depth, Out out, int argc, VALUE *argv) {
1354
1359
  volatile VALUE h = rb_funcall(obj, oj_to_hash_id, 0);
1355
1360
 
1356
1361
  if (T_HASH != rb_type(h)) {
1357
- rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
1362
+ // It seems that ActiveRecord implemented to_hash so that it returns
1363
+ // an Array and not a Hash. To get around that any value returned
1364
+ // will be dumped.
1365
+
1366
+ //rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
1367
+ dump_val(h, depth, out, 0, 0);
1358
1368
  }
1359
1369
  dump_hash(h, Qundef, depth, out->opts->mode, out);
1360
1370
  } else if (rb_respond_to(obj, oj_as_json_id)) {
@@ -1684,7 +1694,12 @@ dump_struct_comp(VALUE obj, int depth, Out out) {
1684
1694
  volatile VALUE h = rb_funcall(obj, oj_to_hash_id, 0);
1685
1695
 
1686
1696
  if (T_HASH != rb_type(h)) {
1687
- rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
1697
+ // It seems that ActiveRecord implemented to_hash so that it returns
1698
+ // an Array and not a Hash. To get around that any value returned
1699
+ // will be dumped.
1700
+
1701
+ //rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
1702
+ dump_val(h, depth, out, 0, 0);
1688
1703
  }
1689
1704
  dump_hash(h, Qundef, depth, out->opts->mode, out);
1690
1705
  } else if (rb_respond_to(obj, oj_as_json_id)) {
@@ -1834,55 +1849,81 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
1834
1849
  dump_cstr(class_name, clen, 0, 0, out);
1835
1850
  *out->cur++ = ',';
1836
1851
  }
1837
- size = d2 * out->indent + 1;
1838
- for (idp = odd->attrs, fp = odd->attrFuncs; 0 != *idp; idp++, fp++) {
1839
- size_t nlen;
1840
-
1841
- if (out->end - out->cur <= (long)size) {
1842
- grow(out, size);
1852
+ if (odd->raw) {
1853
+ v = rb_funcall(obj, *odd->attrs, 0);
1854
+ if (Qundef == v || T_STRING != rb_type(v)) {
1855
+ rb_raise(rb_eEncodingError, "Invalid type for raw JSON.\n");
1856
+ } else {
1857
+ const char *s = rb_string_value_ptr((VALUE*)&v);
1858
+ int len = RSTRING_LEN(v);
1859
+ const char *name = rb_id2name(*odd->attrs);
1860
+ size_t nlen = strlen(name);
1861
+
1862
+ size = len + d2 * out->indent + nlen + 10;
1863
+ if (out->end - out->cur <= (long)size) {
1864
+ grow(out, size);
1865
+ }
1866
+ fill_indent(out, d2);
1867
+ *out->cur++ = '"';
1868
+ memcpy(out->cur, name, nlen);
1869
+ out->cur += nlen;
1870
+ *out->cur++ = '"';
1871
+ *out->cur++ = ':';
1872
+ memcpy(out->cur, s, len);
1873
+ out->cur += len;
1874
+ *out->cur = '\0';
1843
1875
  }
1844
- name = rb_id2name(*idp);
1845
- nlen = strlen(name);
1846
- if (0 != *fp) {
1847
- v = (*fp)(obj);
1848
- } else if (0 == strchr(name, '.')) {
1849
- v = rb_funcall(obj, *idp, 0);
1850
- } else {
1851
- char nbuf[256];
1852
- char *n2 = nbuf;
1853
- char *n;
1854
- char *end;
1855
- ID i;
1856
-
1857
- if (sizeof(nbuf) <= nlen) {
1858
- n2 = strdup(name);
1859
- } else {
1860
- strcpy(n2, name);
1876
+ } else {
1877
+ size = d2 * out->indent + 1;
1878
+ for (idp = odd->attrs, fp = odd->attrFuncs; 0 != *idp; idp++, fp++) {
1879
+ size_t nlen;
1880
+
1881
+ if (out->end - out->cur <= (long)size) {
1882
+ grow(out, size);
1861
1883
  }
1862
- n = n2;
1863
- v = obj;
1864
- while (0 != (end = strchr(n, '.'))) {
1865
- *end = '\0';
1884
+ name = rb_id2name(*idp);
1885
+ nlen = strlen(name);
1886
+ if (0 != *fp) {
1887
+ v = (*fp)(obj);
1888
+ } else if (0 == strchr(name, '.')) {
1889
+ v = rb_funcall(obj, *idp, 0);
1890
+ } else {
1891
+ char nbuf[256];
1892
+ char *n2 = nbuf;
1893
+ char *n;
1894
+ char *end;
1895
+ ID i;
1896
+
1897
+ if (sizeof(nbuf) <= nlen) {
1898
+ n2 = strdup(name);
1899
+ } else {
1900
+ strcpy(n2, name);
1901
+ }
1902
+ n = n2;
1903
+ v = obj;
1904
+ while (0 != (end = strchr(n, '.'))) {
1905
+ *end = '\0';
1906
+ i = rb_intern(n);
1907
+ v = rb_funcall(v, i, 0);
1908
+ n = end + 1;
1909
+ }
1866
1910
  i = rb_intern(n);
1867
1911
  v = rb_funcall(v, i, 0);
1868
- n = end + 1;
1912
+ if (nbuf != n2) {
1913
+ free(n2);
1914
+ }
1869
1915
  }
1870
- i = rb_intern(n);
1871
- v = rb_funcall(v, i, 0);
1872
- if (nbuf != n2) {
1873
- free(n2);
1916
+ fill_indent(out, d2);
1917
+ dump_cstr(name, nlen, 0, 0, out);
1918
+ *out->cur++ = ':';
1919
+ dump_val(v, d2, out, 0, 0);
1920
+ if (out->end - out->cur <= 2) {
1921
+ grow(out, 2);
1874
1922
  }
1923
+ *out->cur++ = ',';
1875
1924
  }
1876
- fill_indent(out, d2);
1877
- dump_cstr(name, nlen, 0, 0, out);
1878
- *out->cur++ = ':';
1879
- dump_val(v, d2, out, 0, 0);
1880
- if (out->end - out->cur <= 2) {
1881
- grow(out, 2);
1882
- }
1883
- *out->cur++ = ',';
1925
+ out->cur--;
1884
1926
  }
1885
- out->cur--;
1886
1927
  *out->cur++ = '}';
1887
1928
  *out->cur = '\0';
1888
1929
  }
@@ -1589,6 +1589,12 @@ doc_close(VALUE self) {
1589
1589
  Oj = rb_define_module("Oj");
1590
1590
  #endif
1591
1591
 
1592
+ static VALUE
1593
+ doc_not_implemented(VALUE self) {
1594
+ rb_raise(rb_eNotImpError, "Not implemented.");
1595
+ return Qnil;
1596
+ }
1597
+
1592
1598
  /* Document-class: Oj::Doc
1593
1599
  *
1594
1600
  * The Doc class is used to parse and navigate a JSON document. The model it
@@ -1653,4 +1659,7 @@ oj_init_doc() {
1653
1659
  rb_define_method(oj_doc_class, "dump", doc_dump, -1);
1654
1660
  rb_define_method(oj_doc_class, "size", doc_size, 0);
1655
1661
  rb_define_method(oj_doc_class, "close", doc_close, 0);
1662
+
1663
+ rb_define_method(oj_doc_class, "clone", doc_not_implemented, 0);
1664
+ rb_define_method(oj_doc_class, "dup", doc_not_implemented, 0);
1656
1665
  }
@@ -55,7 +55,7 @@ read_long(const char *str, size_t len) {
55
55
 
56
56
  static VALUE
57
57
  calc_hash_key(ParseInfo pi, Val kval, char k1) {
58
- VALUE rkey;
58
+ volatile VALUE rkey;
59
59
 
60
60
  if (':' == k1) {
61
61
  rkey = rb_str_new(kval->key + 1, kval->klen - 1);
@@ -388,8 +388,8 @@ hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, volatile VALUE
388
388
  int len = (int)RARRAY_LEN(value);
389
389
 
390
390
  if (2 == klen && 'u' == key[1]) {
391
- VALUE sc;
392
- VALUE e1;
391
+ volatile VALUE sc;
392
+ volatile VALUE e1;
393
393
 
394
394
  if (0 == len) {
395
395
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
@@ -398,9 +398,9 @@ hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, volatile VALUE
398
398
  e1 = *RARRAY_PTR(value);
399
399
  // check for anonymous Struct
400
400
  if (T_ARRAY == rb_type(e1)) {
401
- VALUE args[1024];
402
- VALUE rstr;
403
- int i, cnt = (int)RARRAY_LEN(e1);
401
+ VALUE args[1024];
402
+ volatile VALUE rstr;
403
+ int i, cnt = (int)RARRAY_LEN(e1);
404
404
 
405
405
  for (i = 0; i < cnt; i++) {
406
406
  rstr = rb_ary_entry(e1, i);
@@ -480,8 +480,8 @@ set_obj_ivar(Val parent, Val kval, VALUE value) {
480
480
 
481
481
  if ('~' == *key && Qtrue == rb_obj_is_kind_of(parent->val, rb_eException)) {
482
482
  if (5 == klen && 0 == strncmp("~mesg", key, klen)) {
483
- VALUE args[1];
484
- VALUE prev = parent->val;
483
+ VALUE args[1];
484
+ volatile VALUE prev = parent->val;
485
485
 
486
486
  args[0] = value;
487
487
  parent->val = rb_class_new_instance(1, args, rb_class_of(parent->val));
@@ -652,8 +652,8 @@ hash_set_value(ParseInfo pi, Val kval, VALUE value) {
652
652
  }
653
653
  } else {
654
654
  if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
655
- long len = RARRAY_LEN(value);
656
- VALUE *a = RARRAY_PTR(value);
655
+ long len = RARRAY_LEN(value);
656
+ volatile VALUE *a = RARRAY_PTR(value);
657
657
 
658
658
  if (2 != len) {
659
659
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
@@ -676,6 +676,7 @@ hash_set_value(ParseInfo pi, Val kval, VALUE value) {
676
676
  case T_OBJECT:
677
677
  set_obj_ivar(parent, kval, value);
678
678
  break;
679
+ case T_MODULE:
679
680
  case T_CLASS:
680
681
  if (0 == parent->odd_args) {
681
682
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
@@ -53,6 +53,8 @@ set_class(Odd odd, const char *classname) {
53
53
  odd->clas = rb_const_get(rb_cObject, rb_intern(classname));
54
54
  odd->create_obj = odd->clas;
55
55
  odd->create_op = rb_intern("new");
56
+ odd->is_module = (T_MODULE == rb_type(odd->clas));
57
+ odd->raw = 0;
56
58
  for (np = odd->attr_names, idp = odd->attrs; 0 != *np; np++, idp++) {
57
59
  *idp = rb_intern(*np);
58
60
  }
@@ -139,14 +141,24 @@ oj_odd_init() {
139
141
 
140
142
  Odd
141
143
  oj_get_odd(VALUE clas) {
142
- Odd odd;
144
+ Odd odd;
145
+ const char *classname = NULL;
143
146
 
144
147
  for (odd = odds + odd_cnt - 1; odds <= odd; odd--) {
145
148
  if (clas == odd->clas) {
146
149
  return odd;
147
150
  }
151
+ if (odd->is_module) {
152
+ if (NULL == classname) {
153
+ classname = rb_class2name(clas);
154
+ }
155
+ if (0 == strncmp(odd->classname, classname, odd->clen) &&
156
+ ':' == classname[odd->clen]) {
157
+ return odd;
158
+ }
159
+ }
148
160
  }
149
- return 0;
161
+ return NULL;
150
162
  }
151
163
 
152
164
  Odd
@@ -157,6 +169,11 @@ oj_get_oddc(const char *classname, size_t len) {
157
169
  if (len == odd->clen && 0 == strncmp(classname, odd->classname, len)) {
158
170
  return odd;
159
171
  }
172
+ if (odd->is_module &&
173
+ 0 == strncmp(odd->classname, classname, odd->clen) &&
174
+ ':' == classname[odd->clen]) {
175
+ return odd;
176
+ }
160
177
  }
161
178
  return 0;
162
179
  }
@@ -195,7 +212,7 @@ oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
195
212
  }
196
213
 
197
214
  void
198
- oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members) {
215
+ oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw) {
199
216
  Odd odd;
200
217
  const char **np;
201
218
  ID *ap;
@@ -215,6 +232,8 @@ oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE
215
232
  odd->create_obj = create_object;
216
233
  odd->create_op = SYM2ID(create_method);
217
234
  odd->attr_cnt = mcnt;
235
+ odd->is_module = (T_MODULE == rb_type(clas));
236
+ odd->raw = raw;
218
237
  for (ap = odd->attrs, np = odd->attr_names, fp = odd->attrFuncs; 0 < mcnt; mcnt--, ap++, np++, members++, fp++) {
219
238
  *fp = 0;
220
239
  switch (rb_type(*members)) {
@@ -31,6 +31,8 @@
31
31
  #ifndef __OJ_ODD_H__
32
32
  #define __OJ_ODD_H__
33
33
 
34
+ #include <stdbool.h>
35
+
34
36
  #include "ruby.h"
35
37
 
36
38
  #define MAX_ODD_ARGS 10
@@ -40,10 +42,12 @@ typedef VALUE (*AttrGetFunc)(VALUE obj);
40
42
  typedef struct _Odd {
41
43
  const char *classname;
42
44
  size_t clen;
43
- VALUE clas; // Ruby class
45
+ VALUE clas; // Ruby class or module
44
46
  VALUE create_obj;
45
47
  ID create_op;
46
48
  int attr_cnt;
49
+ bool is_module;
50
+ bool raw;
47
51
  const char *attr_names[MAX_ODD_ARGS]; // 0 terminated attr IDs
48
52
  ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
49
53
  AttrGetFunc attrFuncs[MAX_ODD_ARGS];
@@ -60,6 +64,6 @@ extern Odd oj_get_oddc(const char *classname, size_t len);
60
64
  extern OddArgs oj_odd_alloc_args(Odd odd);
61
65
  extern void oj_odd_free(OddArgs args);
62
66
  extern int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value);
63
- extern void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members);
67
+ extern void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw);
64
68
 
65
69
  #endif /* __OJ_ODD_H__ */
@@ -963,7 +963,7 @@ to_stream(int argc, VALUE *argv, VALUE self) {
963
963
  * normal way. It is not intended as a hook for changing the output of all
964
964
  * classes as it is not optimized for large numbers of classes.
965
965
  *
966
- * @param [Class] clas Class to be made special
966
+ * @param [Class|Module] clas Class or Module to be made special
967
967
  * @param [Object] create_object object to call the create method on
968
968
  * @param [Symbol] create_method method on the clas that will create a new
969
969
  * instance of the clas when given all the member values in the
@@ -976,12 +976,59 @@ register_odd(int argc, VALUE *argv, VALUE self) {
976
976
  if (3 > argc) {
977
977
  rb_raise(rb_eArgError, "incorrect number of arguments.");
978
978
  }
979
- Check_Type(argv[0], T_CLASS);
979
+ switch (rb_type(*argv)) {
980
+ case T_CLASS:
981
+ case T_MODULE:
982
+ break;
983
+ default:
984
+ rb_raise(rb_eTypeError, "expected a class or module.");
985
+ break;
986
+ }
987
+ Check_Type(argv[2], T_SYMBOL);
988
+ if (MAX_ODD_ARGS < argc - 2) {
989
+ rb_raise(rb_eArgError, "too many members.");
990
+ }
991
+ oj_reg_odd(argv[0], argv[1], argv[2], argc - 3, argv + 3, false);
992
+
993
+ return Qnil;
994
+ }
995
+
996
+ /* call-seq: register_odd_raw(clas, create_object, create_method, dump_method)
997
+ *
998
+ * Registers a class as special and expect the output to be a string that can be
999
+ * included in the dumped JSON directly. This is useful for working around
1000
+ * subclasses of primitive types as is done with ActiveSupport classes. The use
1001
+ * of this function should be limited to just classes that can not be handled in
1002
+ * the normal way. It is not intended as a hook for changing the output of all
1003
+ * classes as it is not optimized for large numbers of classes. Be careful with
1004
+ * this option as the JSON may be incorrect if invalid JSON is returned.
1005
+ *
1006
+ * @param [Class|Module] clas Class or Module to be made special
1007
+ * @param [Object] create_object object to call the create method on
1008
+ * @param [Symbol] create_method method on the clas that will create a new
1009
+ * instance of the clas when given all the member values in the
1010
+ * order specified.
1011
+ * @param [Symbol|String] dump_method method to call on the object being
1012
+ * serialized to generate the raw JSON.
1013
+ */
1014
+ static VALUE
1015
+ register_odd_raw(int argc, VALUE *argv, VALUE self) {
1016
+ if (3 > argc) {
1017
+ rb_raise(rb_eArgError, "incorrect number of arguments.");
1018
+ }
1019
+ switch (rb_type(*argv)) {
1020
+ case T_CLASS:
1021
+ case T_MODULE:
1022
+ break;
1023
+ default:
1024
+ rb_raise(rb_eTypeError, "expected a class or module.");
1025
+ break;
1026
+ }
980
1027
  Check_Type(argv[2], T_SYMBOL);
981
1028
  if (MAX_ODD_ARGS < argc - 2) {
982
1029
  rb_raise(rb_eArgError, "too many members.");
983
1030
  }
984
- oj_reg_odd(argv[0], argv[1], argv[2], argc - 3, argv + 3);
1031
+ oj_reg_odd(argv[0], argv[1], argv[2], 1, argv + 3, true);
985
1032
 
986
1033
  return Qnil;
987
1034
  }
@@ -2032,6 +2079,7 @@ void Init_oj() {
2032
2079
  rb_define_module_function(Oj, "to_file", to_file, -1);
2033
2080
  rb_define_module_function(Oj, "to_stream", to_stream, -1);
2034
2081
  rb_define_module_function(Oj, "register_odd", register_odd, -1);
2082
+ rb_define_module_function(Oj, "register_odd_raw", register_odd_raw, -1);
2035
2083
 
2036
2084
  rb_define_module_function(Oj, "saj_parse", oj_saj_parse, -1);
2037
2085
  rb_define_module_function(Oj, "sc_parse", oj_sc_parse, -1);
@@ -519,7 +519,7 @@ read_num(ParseInfo pi) {
519
519
 
520
520
  static void
521
521
  array_start(ParseInfo pi) {
522
- VALUE v = pi->start_array(pi);
522
+ volatile VALUE v = pi->start_array(pi);
523
523
 
524
524
  stack_push(&pi->stack, v, NEXT_ARRAY_NEW);
525
525
  }
@@ -688,7 +688,7 @@ oj_parse2(ParseInfo pi) {
688
688
 
689
689
  VALUE
690
690
  oj_num_as_value(NumInfo ni) {
691
- VALUE rnum = Qnil;
691
+ volatile VALUE rnum = Qnil;
692
692
 
693
693
  if (ni->infinity) {
694
694
  if (ni->neg) {
@@ -781,7 +781,7 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
781
781
  char *buf = 0;
782
782
  volatile VALUE input;
783
783
  volatile VALUE wrapped_stack;
784
- VALUE result = Qnil;
784
+ volatile VALUE result = Qnil;
785
785
  int line = 0;
786
786
  int free_json = 0;
787
787
 
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '2.12.14'
4
+ VERSION = '2.13.0'
5
5
  end
@@ -131,6 +131,46 @@ class ObjectJuice < Minitest::Test
131
131
  alias == eql?
132
132
  end
133
133
 
134
+ class Raw
135
+ attr_accessor :json
136
+
137
+ def initialize(j)
138
+ @json = j
139
+ end
140
+
141
+ def to_json(*a)
142
+ @json
143
+ end
144
+
145
+ def self.create(h)
146
+ h
147
+ end
148
+ end # Raw
149
+
150
+ module Ichi
151
+ module Ni
152
+ def self.direct(h)
153
+ h
154
+ end
155
+
156
+ module San
157
+ class Shi
158
+
159
+ attr_accessor :hash
160
+
161
+ def initialize(h)
162
+ @hash = h
163
+ end
164
+
165
+ def dump()
166
+ @hash
167
+ end
168
+
169
+ end # Shi
170
+ end # San
171
+ end # Ni
172
+ end # Ichi
173
+
134
174
  def setup
135
175
  @default_options = Oj.default_options
136
176
  end
@@ -661,6 +701,22 @@ class ObjectJuice < Minitest::Test
661
701
  dump_and_load(Date.new(2012, 6, 19), false)
662
702
  end
663
703
 
704
+ def test_odd_raw
705
+ Oj.register_odd_raw(Raw, Raw, :create, :to_json)
706
+ json = Oj.dump(Raw.new(%|{"a":1}|), :mode => :object)
707
+ assert_equal(%|{"^O":"ObjectJuice::Raw","to_json":{"a":1}}|, json)
708
+ h = Oj.load(json, :mode => :object)
709
+ assert_equal({'a' => 1}, h)
710
+ end
711
+
712
+ def test_odd_mod
713
+ Oj.register_odd(Ichi::Ni, Ichi::Ni, :direct, :dump)
714
+ json = Oj.dump(Ichi::Ni::San::Shi.new({'a' => 1}), :mode => :object)
715
+ assert_equal(%|{"^O":"ObjectJuice::Ichi::Ni::San::Shi","dump":{"a":1}}|, json)
716
+ h = Oj.load(json, :mode => :object)
717
+ assert_equal({'a' => 1}, h)
718
+ end
719
+
664
720
  def test_auto_string
665
721
  s = AutoStrung.new("Pete", true)
666
722
  dump_and_load(s, false)
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.12.14
4
+ version: 2.13.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: 2015-09-14 00:00:00.000000000 Z
11
+ date: 2015-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler