错误地转义了JSON编码(Rails 3,Ruby 1.9.2)

Mic*_*are 19 ruby encoding json ruby-on-rails

在我的控制器中,以下工作(打印"oké")

puts obj.inspect
Run Code Online (Sandbox Code Playgroud)

但这不会(呈现"ok\u00e9")

render :json => obj
Run Code Online (Sandbox Code Playgroud)

显然,该to_json方法会转义unicode字符.有没有办法防止这种情况发生?

Wou*_*ter 34

要将\ uXXXX代码设置回utf-8:

json_string.gsub!(/\\u([0-9a-z]{4})/) {|s| [$1.to_i(16)].pack("U")}
Run Code Online (Sandbox Code Playgroud)


Dav*_*eus 21

你可以通过猴子修补muu提到的方法来防止它太短.将以下内容放入config/initializers/patches.rb(或用于修补内容的类似文件)并重新启动rails进程以使更改生效.

module ActiveSupport::JSON::Encoding
  class << self
    def 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] }
      json = %("#{json}")
      json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding)
      json
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

请注意,无法保证该补丁可以与未来版本的ActiveSupport一起使用.撰写这篇文章时使用的版本是3.1.3.


mu *_*ort 15

如果你深入挖掘源代码,你最终会来到ActiveSupport::JSON::Encoding这个escape方法:

def 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
Run Code Online (Sandbox Code Playgroud)

各种gsub调用强制非ASCII UTF-8到\uXXXX您所看到的符号.十六进制编码的UTF-8对于处理JSON的任何内容都应该是可接受的,但是您可以随时对JSON(或修改后的JSON转发器中的猴子补丁)进行后处理,\uXXXX以便在必要时将符号转换为原始UTF-8.

我同意强制JSON为7bit-clean有点假,但你去了.

简答:不.


old*_*god 12

字符没有使用其他方法转义为unicode,Rails2.3.11/Ruby1.8所以我使用了以下内容:

render :json => JSON::dump(obj)
Run Code Online (Sandbox Code Playgroud)


Ben*_*ank 9

这是正确的编码.JSON不requre转义Unicode字符,但它是常见的JSON库以产生仅包含7位ASCII字符输出,以避免在运输任何潜在的编码问题.

任何JSON解释器都可以使用该字符串并重现原始字符串.要查看此操作,只需输入javascript:alert("ok\u00e9")浏览器的位置栏即可.