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 +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
|
[![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](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
|