Skip to content

Commit db0378f

Browse files
committed
Support calling to_s/to_json
1 parent 4cb2c3a commit db0378f

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

ext/rapidjson/cext.cc

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
#include "cext.hh"
22

3-
VALUE rb_mRapidjson;
4-
VALUE rb_eParseError;
5-
VALUE rb_eEncodeError;
6-
73
#include "rapidjson/writer.h"
84
#include "rapidjson/prettywriter.h"
95
#include "rapidjson/error/en.h"
106

7+
static VALUE rb_mRapidjson;
8+
static VALUE rb_eParseError;
9+
static VALUE rb_eEncodeError;
10+
11+
static ID id_to_json;
12+
static ID id_to_s;
13+
1114
#include "encoder.hh"
1215
#include "parser.hh"
1316

@@ -57,6 +60,9 @@ VALUE valid_json_p(VALUE _self, VALUE string) {
5760
extern "C" void
5861
Init_rapidjson(void)
5962
{
63+
id_to_s = rb_intern("to_s");
64+
id_to_json = rb_intern("to_json");
65+
6066
rb_mRapidjson = rb_define_module("RapidJSON");
6167
rb_define_module_function(rb_mRapidjson, "encode", encode, 1);
6268
rb_define_module_function(rb_mRapidjson, "pretty_encode", pretty_encode, 1);

ext/rapidjson/encoder.hh

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,25 @@ class RubyObjectEncoder {
8484
encode_string(rb_sym2str(v));
8585
}
8686

87+
void encode_raw_json_str(VALUE s) {
88+
const char *cstr = RSTRING_PTR(s);
89+
size_t len = RSTRING_LEN(s);
90+
91+
writer.RawValue(cstr, len, kObjectType);
92+
}
93+
94+
void encode_generic(VALUE obj) {
95+
if (rb_respond_to(obj, id_to_json)) {
96+
VALUE str = rb_funcall(obj, id_to_json, 0);
97+
Check_Type(str, T_STRING);
98+
encode_raw_json_str(str);
99+
} else {
100+
VALUE str = rb_funcall(obj, id_to_s, 0);
101+
Check_Type(str, T_STRING);
102+
encode_string(str);
103+
}
104+
}
105+
87106
void encode_any(VALUE v) {
88107
switch(rb_type(v)) {
89108
case T_NIL:
@@ -110,7 +129,7 @@ class RubyObjectEncoder {
110129
case T_SYMBOL:
111130
return encode_symbol(v);
112131
default:
113-
raise_unknown(v);
132+
encode_generic(v);
114133
}
115134
}
116135

test/test_encoder.rb

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,27 @@ def test_encode_symbol
7373
end
7474

7575
def test_encode_object
76-
ex = assert_raises RapidJSON::EncodeError do
77-
encode(Object.new)
76+
assert_match(/\A"#<Object:0x[0-9a-f]+>"\z/, encode(Object.new))
77+
end
78+
79+
def test_to_json
80+
klass = Class.new do
81+
def to_json
82+
'{ "amazing":"custom json" }'
83+
end
7884
end
79-
assert_match(/can't encode type/, ex.message)
85+
86+
assert_equal '{ "amazing":"custom json" }', encode(klass.new)
87+
end
88+
89+
def test_to_s
90+
klass = Class.new do
91+
def to_s
92+
"amazing object!"
93+
end
94+
end
95+
96+
assert_equal '"amazing object!"', encode(klass.new)
8097
end
8198

8299
def test_encode_true

0 commit comments

Comments
 (0)