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 +4 -4
- data/README.md +9 -4
- data/ext/oj/dump.c +85 -44
- data/ext/oj/fast.c +9 -0
- data/ext/oj/object.c +11 -10
- data/ext/oj/odd.c +22 -3
- data/ext/oj/odd.h +6 -2
- data/ext/oj/oj.c +51 -3
- data/ext/oj/parse.c +3 -3
- data/lib/oj/version.rb +1 -1
- data/test/test_object.rb +56 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd957508587371c18e701b638fcf8191b3bc444d
|
4
|
+
data.tar.gz: aef52ecc143c4db76dfd1f9c64914a8a9021ad71
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
[](http://travis-ci.org/ohler55/oj)
|
28
28
|
|
29
|
-
## Release 2.
|
29
|
+
## Release 2.13.0
|
30
30
|
|
31
|
-
-
|
32
|
-
|
33
|
-
instead
|
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
|
|
data/ext/oj/dump.c
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
|
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
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
1850
|
-
|
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
|
-
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
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
|
-
|
1912
|
+
if (nbuf != n2) {
|
1913
|
+
free(n2);
|
1914
|
+
}
|
1869
1915
|
}
|
1870
|
-
|
1871
|
-
|
1872
|
-
|
1873
|
-
|
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
|
-
|
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
|
}
|
data/ext/oj/fast.c
CHANGED
@@ -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
|
}
|
data/ext/oj/object.c
CHANGED
@@ -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
|
402
|
-
VALUE rstr;
|
403
|
-
int
|
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
|
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
|
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)));
|
data/ext/oj/odd.c
CHANGED
@@ -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
|
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
|
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)) {
|
data/ext/oj/odd.h
CHANGED
@@ -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__ */
|
data/ext/oj/oj.c
CHANGED
@@ -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
|
-
|
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],
|
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);
|
data/ext/oj/parse.c
CHANGED
@@ -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
|
784
|
+
volatile VALUE result = Qnil;
|
785
785
|
int line = 0;
|
786
786
|
int free_json = 0;
|
787
787
|
|
data/lib/oj/version.rb
CHANGED
data/test/test_object.rb
CHANGED
@@ -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.
|
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-
|
11
|
+
date: 2015-10-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|