在将哈希值转换为json字符串时,我遇到了特殊字符问题。
使用Ruby 2.0 / Rails 3.2.21,即
,一切正常puts "“".to_json
#"\u201c"
但是使用Ruby 2.3.0 / Rails 4.2.5.1我得到了
puts "“".to_json
#"“"
有没有办法强制Ruby 2.3.0将特殊字符转换为unicode样式字符串(\uXXXX
)?
注:
请注意,在Ruby 2.3 / Rails 4中,我们得到了
"“".to_json.bytesize == 5 #true
然而,在2.0中我们得到了
"“".to_json.bytesize == 8 #true
很明显,字符串本身是不同的,而不是不同的输出格式。
答案 0 :(得分:5)
我❤Rails(开个玩笑。)
在Rails3中有一个hilarious method来破坏JSON中的UTF-8。感谢DHH,Rails4摆脱了这个缺点。
那么,是否需要时间倒退机器,最简单的方法是monkeypatch ::ActiveSupport::JSON::Encoding#escape
:
module ::ActiveSupport::JSON::Encoding
def self.escape(string)
if string.respond_to?(:force_encoding)
string = string.encode(::Encoding::UTF_8, :undef => :replace)
.force_encoding(::Encoding::BINARY)
end
json = string.
gsub(escape_regex) { |s| ESCAPED_CHARS[s] }.
gsub(/([\xC0-\xDF][\x80-\xBF]|
[\xE0-\xEF][\x80-\xBF]{2}|
[\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s|
s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/n, '\\\\u\&')
}
json = %("#{json}")
json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding)
json
end
end
更强大的解决方案是破坏结果:
class String
def rails3_style
string = encode(::Encoding::UTF_8, :undef => :replace).
force_encoding(::Encoding::BINARY)
json = string.
gsub(/([\xC0-\xDF][\x80-\xBF]|
[\xE0-\xEF][\x80-\xBF]{2}|
[\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s|
s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/n, '\\\\u\&')
}
json = %("#{json}")
json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding)
json
end
end
puts "“".to_json.rails3_style
#⇒ "\u201c"
我几乎无法理解为什么有人可能会故意这样做,但解决方案就在这里。