Skip to content

Commit 2f76147

Browse files
committed
Raise JSON::GeneratorError instead of Encoding::UndefinedConversionError
Followup: ruby#633 That's what was raised historically. You could argue that this new exception is more precise, but I've encountered some real production code that expected the old behavior and that was broken by this change.
1 parent e3a3695 commit 2f76147

File tree

4 files changed

+38
-12
lines changed

4 files changed

+38
-12
lines changed

ext/json/ext/generator/generator.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,10 @@ static VALUE generate_json_rescue(VALUE d, VALUE exc)
954954
struct generate_json_data *data = (struct generate_json_data *)d;
955955
fbuffer_free(data->buffer);
956956

957+
if (RBASIC_CLASS(exc) == rb_path2class("Encoding::UndefinedConversionError")) {
958+
exc = rb_exc_new_str(eGeneratorError, rb_funcall(exc, rb_intern("message"), 0));
959+
}
960+
957961
rb_exc_raise(exc);
958962

959963
return Qundef;

java/src/json/ext/Generator.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.jruby.runtime.ThreadContext;
1818
import org.jruby.runtime.builtin.IRubyObject;
1919
import org.jruby.util.ByteList;
20+
import org.jruby.exceptions.RaiseException;
2021

2122
public final class Generator {
2223
private Generator() {
@@ -390,14 +391,19 @@ void generate(Session session, RubyString object, ByteList buffer) {
390391
RuntimeInfo info = session.getInfo();
391392
RubyString src;
392393

393-
if (object.encoding(session.getContext()) != info.utf8.get()) {
394-
src = (RubyString)object.encode(session.getContext(),
395-
info.utf8.get());
396-
} else {
397-
src = object;
398-
}
394+
try {
395+
if (object.encoding(session.getContext()) != info.utf8.get()) {
396+
src = (RubyString)object.encode(session.getContext(),
397+
info.utf8.get());
398+
} else {
399+
src = object;
400+
}
399401

400-
session.getStringEncoder().encode(src.getByteList(), buffer);
402+
session.getStringEncoder().encode(src.getByteList(), buffer);
403+
} catch (RaiseException re) {
404+
throw Utils.newException(session.getContext(), Utils.M_GENERATOR_ERROR,
405+
re.getMessage());
406+
}
401407
}
402408
};
403409

lib/json/pure/generator.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,11 @@ def generate(obj)
347347
if Regexp.method_defined?(:match?)
348348
private def fast_serialize_string(string, buf) # :nodoc:
349349
buf << '"'
350-
string = string.encode(::Encoding::UTF_8) unless string.encoding == ::Encoding::UTF_8
350+
begin
351+
string = string.encode(::Encoding::UTF_8) unless string.encoding == ::Encoding::UTF_8
352+
rescue Encoding::UndefinedConversionError => error
353+
raise GeneratorError, error.message
354+
end
351355
raise GeneratorError, "source sequence is illegal/malformed utf-8" unless string.valid_encoding?
352356

353357
if /["\\\x0-\x1f]/n.match?(string)
@@ -536,7 +540,11 @@ def to_json(state = nil, *args)
536540
end
537541
string = self
538542
else
539-
string = encode(::Encoding::UTF_8)
543+
begin
544+
string = encode(::Encoding::UTF_8)
545+
rescue Encoding::UndefinedConversionError => error
546+
raise GeneratorError, error.message
547+
end
540548
end
541549
if state.ascii_only?
542550
%("#{JSON.utf8_to_json_ascii(string, state.script_safe)}")

test/json/json_generator_test.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -470,12 +470,20 @@ def test_invalid_encoding_string
470470
end
471471
assert_includes error.message, "source sequence is illegal/malformed utf-8"
472472

473-
assert_raise(Encoding::UndefinedConversionError) do
473+
assert_raise(JSON::GeneratorError) do
474+
JSON.dump("\x82\xAC\xEF".b)
475+
end
476+
477+
assert_raise(JSON::GeneratorError) do
474478
"\x82\xAC\xEF".b.to_json
475479
end
476480

477-
assert_raise(Encoding::UndefinedConversionError) do
478-
JSON.dump("\x82\xAC\xEF".b)
481+
assert_raise(JSON::GeneratorError) do
482+
["\x82\xAC\xEF".b].to_json
483+
end
484+
485+
assert_raise(JSON::GeneratorError) do
486+
{ foo: "\x82\xAC\xEF".b }.to_json
479487
end
480488
end
481489

0 commit comments

Comments
 (0)