summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2014-10-07 15:58:18 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2014-10-07 15:58:18 -0700
commit6e19eb693350f198f9b18609c3f1a89b3138b79e (patch)
tree41e85ca3d6b4dfa79b63c0d31f07116b8f141a18
parentc5d0f4c89fa5a493fd9638d232f70088b4d0556e (diff)
parentd713d2681aba154fc83d41b32bbdbb99c2055b61 (diff)
downloadffi-yajl-6e19eb693350f198f9b18609c3f1a89b3138b79e.tar.gz
Merge pull request #25 from tyler-ball/tball/remove_to_json
If an object does not have .to_json, we no longer try to call it
-rw-r--r--CHANGELOG.md3
-rw-r--r--ext/ffi_yajl/ext/encoder/encoder.c20
-rw-r--r--lib/ffi_yajl/ffi/encoder.rb11
-rw-r--r--spec/ffi_yajl/encoder_spec.rb17
4 files changed, 42 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 59eb314..651c40c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@
### Changes
+* Encoding Object will no longer blindly call .to_json(). It will first check if the Object supports a .to_json() method
+and if it does not it will call .to_s(). This prevents NoSuchMethod errors when not using the JSON gem.
+
### Bugs fixed
* Change Config to RbConfig for FFI-based dlopen for non-DL/non-Fiddle fallback.
diff --git a/ext/ffi_yajl/ext/encoder/encoder.c b/ext/ffi_yajl/ext/encoder/encoder.c
index 0c917cb..90b125b 100644
--- a/ext/ffi_yajl/ext/encoder/encoder.c
+++ b/ext/ffi_yajl/ext/encoder/encoder.c
@@ -272,14 +272,20 @@ static VALUE rb_cObject_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
yajl_gen_status status;
ID sym_to_json = rb_intern("to_json");
VALUE str;
- VALUE json_opts = rb_hash_aref(state, rb_str_new2("json_opts"));
- struct yajl_gen_t *yajl_gen;
- Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen);
- str = rb_funcall(self, sym_to_json, 1, json_opts);
- CHECK_STATUS(
- yajl_gen_number(yajl_gen, (char *)RSTRING_PTR(str), RSTRING_LEN(str))
- );
+ if ( rb_respond_to(self, sym_to_json) ) {
+ VALUE json_opts = rb_hash_aref(state, rb_str_new2("json_opts"));
+ struct yajl_gen_t *yajl_gen;
+ Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen);
+
+ str = rb_funcall(self, sym_to_json, 1, json_opts);
+ CHECK_STATUS(
+ yajl_gen_number(yajl_gen, (char *)RSTRING_PTR(str), RSTRING_LEN(str))
+ );
+ } else {
+ object_to_s_ffi_yajl(self, rb_yajl_gen, state);
+ }
+
return Qnil;
}
diff --git a/lib/ffi_yajl/ffi/encoder.rb b/lib/ffi_yajl/ffi/encoder.rb
index 3df366c..8177f5f 100644
--- a/lib/ffi_yajl/ffi/encoder.rb
+++ b/lib/ffi_yajl/ffi/encoder.rb
@@ -201,8 +201,15 @@ end
# I feel dirty
class Object
def ffi_yajl(yajl_gen, state)
- json = self.to_json(state[:json_opts])
- if ( status = FFI_Yajl.yajl_gen_number(yajl_gen, json, json.bytesize) ) != 0
+ if self.respond_to?(:to_json)
+ json = self.to_json(state[:json_opts])
+ # #yajl_gen_number outputs a string without quotes around it
+ status = FFI_Yajl.yajl_gen_number(yajl_gen, json, json.bytesize)
+ else
+ str = self.to_s
+ status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize)
+ end
+ if ( status ) != 0
FFI_Yajl::Encoder.raise_error_for_status(status)
end
end
diff --git a/spec/ffi_yajl/encoder_spec.rb b/spec/ffi_yajl/encoder_spec.rb
index f658d95..02bc020 100644
--- a/spec/ffi_yajl/encoder_spec.rb
+++ b/spec/ffi_yajl/encoder_spec.rb
@@ -87,4 +87,21 @@ describe "FFI_Yajl::Encoder" do
expect(encoder.encode(ruby)).to eq( %q{"2001-02-03T04:05:06+07:00"} )
end
+ describe "testing .to_json for Objects" do
+ class NoToJson; end
+ class HasToJson
+ def to_json(*args)
+ "{}"
+ end
+ end
+
+ it "calls .to_s for objects without .to_json" do
+ expect(encoder.encode(NoToJson.new)).to match(/^"#<NoToJson:\w+>"$/)
+ end
+
+ it "calls .to_json for objects wit .to_json" do
+ expect(encoder.encode(HasToJson.new)).to eq("{}")
+ end
+ end
+
end