summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Frank <flori@ping.de>2009-10-19 23:29:57 +0200
committerFlorian Frank <flori@ping.de>2009-10-19 23:29:57 +0200
commitd052678f86b0832af2fda6489ca179637b055f28 (patch)
treed7eab0248fc27c97418edabbdb1b2693836a6609
parented80ac83bca17c55aedfbc916b0431d81beeb521 (diff)
downloadjson-d052678f86b0832af2fda6489ca179637b055f28.tar.gz
added conversion to utf8 to generators as well
-rw-r--r--ext/json/ext/generator/generator.c14
-rw-r--r--lib/json/pure/generator.rb30
-rw-r--r--tests/test_json_encoding.rb36
3 files changed, 58 insertions, 22 deletions
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index 9bcd580..2cd1629 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -24,6 +24,8 @@
#ifdef HAVE_RUBY_ENCODING_H
#include "ruby/encoding.h"
#define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
+static VALUE mEncoding_UTF_8;
+static ID i_encoding, i_encode;
#else
#define FORCE_UTF8(obj)
#endif
@@ -357,7 +359,12 @@ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
{
VALUE result = rb_str_buf_new(RSTRING_LEN(self));
rb_str_buf_cat2(result, "\"");
- JSON_convert_UTF8_to_JSON(result, self, strictConversion);
+ if (rb_funcall(self, i_encoding, 0) == mEncoding_UTF_8) {
+ JSON_convert_UTF8_to_JSON(result, self, strictConversion);
+ } else {
+ VALUE string = rb_funcall(self, i_encode, 1, mEncoding_UTF_8);
+ JSON_convert_UTF8_to_JSON(result, string, strictConversion);
+ }
rb_str_buf_cat2(result, "\"");
FORCE_UTF8(result);
return result;
@@ -916,4 +923,9 @@ void Init_generator()
i_unpack = rb_intern("unpack");
i_create_id = rb_intern("create_id");
i_extend = rb_intern("extend");
+#ifdef HAVE_RUBY_ENCODING_H
+ mEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
+ i_encoding = rb_intern("encoding");
+ i_encode = rb_intern("encode");
+#endif
}
diff --git a/lib/json/pure/generator.rb b/lib/json/pure/generator.rb
index 2b7eeb7..57ef483 100644
--- a/lib/json/pure/generator.rb
+++ b/lib/json/pure/generator.rb
@@ -38,11 +38,11 @@ module JSON
# Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
# UTF16 big endian characters as \u????, and return it.
- if String.method_defined?(:force_encoding)
+ if defined?(::Encoding)
def utf8_to_json(string) # :nodoc:
string = string.dup
string << '' # XXX workaround: avoid buffer sharing
- string.force_encoding(Encoding::ASCII_8BIT)
+ string.force_encoding(::Encoding::ASCII_8BIT)
string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
string.gsub!(/(
(?:
@@ -56,7 +56,7 @@ module JSON
s = JSON::UTF8toUTF16.iconv(c).unpack('H*')[0]
s.gsub!(/.{4}/n, '\\\\u\&')
}
- string.force_encoding(Encoding::UTF_8)
+ string.force_encoding(::Encoding::UTF_8)
string
rescue Iconv::Failure => e
raise GeneratorError, "Caught #{e.class}: #{e}"
@@ -369,11 +369,25 @@ module JSON
end
module String
- # This string should be encoded with UTF-8 A call to this method
- # returns a JSON string encoded with UTF16 big endian characters as
- # \u????.
- def to_json(*)
- '"' << JSON.utf8_to_json(self) << '"'
+ if defined?(::Encoding)
+ # This string should be encoded with UTF-8 A call to this method
+ # returns a JSON string encoded with UTF16 big endian characters as
+ # \u????.
+ def to_json(*)
+ if encoding == ::Encoding::UTF_8
+ '"' << JSON.utf8_to_json(self) << '"'
+ else
+ string = encode(::Encoding::UTF_8)
+ '"' << JSON.utf8_to_json(string) << '"'
+ end
+ end
+ else
+ # This string should be encoded with UTF-8 A call to this method
+ # returns a JSON string encoded with UTF16 big endian characters as
+ # \u????.
+ def to_json(*)
+ '"' << JSON.utf8_to_json(self) << '"'
+ end
end
# Module that holds the extinding methods if, the String module is
diff --git a/tests/test_json_encoding.rb b/tests/test_json_encoding.rb
index f46b476..bfb3e60 100644
--- a/tests/test_json_encoding.rb
+++ b/tests/test_json_encoding.rb
@@ -14,7 +14,9 @@ class TC_JSONEncoding < Test::Unit::TestCase
def setup
@utf_8 = '["© ≠ €!"]'
- @decoded = [ "© ≠ €!" ]
+ @parsed = [ "© ≠ €!" ]
+ @utf_16_data = Iconv.iconv('utf-16be', 'utf-8', @parsed.first)
+ @generated = '["\u00a9 \u2260 \u20ac!"]'
if defined?(::Encoding)
@utf_8_ascii_8bit = @utf_8.dup.force_encoding(Encoding::ASCII_8BIT)
@utf_16be, = Iconv.iconv('utf-16be', 'utf-8', @utf_8)
@@ -38,20 +40,28 @@ class TC_JSONEncoding < Test::Unit::TestCase
end
end
- def test_decode
- assert @decoded, JSON.parse(@utf_8)
- assert @decoded, JSON.parse(@utf_16be)
- assert @decoded, JSON.parse(@utf_16le)
- assert @decoded, JSON.parse(@utf_32be)
- assert @decoded, JSON.parse(@utf_32le)
+ def test_parse
+ assert_equal @parsed, JSON.parse(@utf_8)
+ assert_equal @parsed, JSON.parse(@utf_16be)
+ assert_equal @parsed, JSON.parse(@utf_16le)
+ assert_equal @parsed, JSON.parse(@utf_32be)
+ assert_equal @parsed, JSON.parse(@utf_32le)
end
- def test_decode_ascii_8bit
- assert @decoded, JSON.parse(@utf_8_ascii_8bit)
- assert @decoded, JSON.parse(@utf_16be_ascii_8bit)
- assert @decoded, JSON.parse(@utf_16le_ascii_8bit)
- assert @decoded, JSON.parse(@utf_32be_ascii_8bit)
- assert @decoded, JSON.parse(@utf_32le_ascii_8bit)
+ def test_parse_ascii_8bit
+ assert_equal @parsed, JSON.parse(@utf_8_ascii_8bit)
+ assert_equal @parsed, JSON.parse(@utf_16be_ascii_8bit)
+ assert_equal @parsed, JSON.parse(@utf_16le_ascii_8bit)
+ assert_equal @parsed, JSON.parse(@utf_32be_ascii_8bit)
+ assert_equal @parsed, JSON.parse(@utf_32le_ascii_8bit)
end
+ def test_generate
+ assert_equal @generated, JSON.generate(@parsed)
+ if defined?(::Encoding)
+ assert_equal @generated, JSON.generate(@utf_16_data)
+ else
+ assert_raises(JSON::GeneratorError) { JSON.generate(@utf_16_data) }
+ end
+ end
end