oj 2.12.14 → 2.13.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: 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