ruby-on-rails - to_json 不将特殊字符转换为 unicode 样式

标签 ruby-on-rails ruby json

我在将哈希值转换为 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

很明显,不同的是字符串本身,而不是不同的输出格式。

最佳答案

我 ❤ Rails(开玩笑。)

在 Rails3 中有一个 hilarious method损坏 JSON 中的 UTF-8。 Rails4,感谢 DHH,摆脱了这个缺点。

因此,无论是否想要时光倒流机,最简单的方法是猴子补丁 ::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"

我很难理解为什么有人会故意这样做,但解决方案就在这里。

关于ruby-on-rails - to_json 不将特殊字符转换为 unicode 样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37988287/

相关文章:

ruby-on-rails - 检查是否返回 csv

ruby-on-rails - Ruby:时间值的数学函数

带有消费者线程和作业队列的 Ruby Sinatra

ruby - 这个 sprintf 调用在 1.9.2 中是否损坏?

ruby-on-rails - Rails - 不知道如何将表单中的数据保存到另一个模型中

JSON 查询 - 执行失败

javascript - 在 Action Mailer 中创建完整的 url 链接而不使用 url 助手

ruby-on-rails - 运行 Rspec 时出现 "No such file to load"错误

json - 使用 SwiftyJSON 错误?

php - 我的 JSON 没有被 PHP 解码