![](/img/trans.png)
[英]Ruby 1.8.7 - Ruby 1.9.2 and Rails 3.0.0 'Encoding' Model Name Conflict
[英]JSON encoding wrongly escaped (Rails 3, Ruby 1.9.2)
在我的控制器中,以下工作(打印“oké”)
puts obj.inspect
但這不會(呈現“ok \\ u00e9”)
render :json => obj
顯然, to_json
方法會轉義unicode字符。 有沒有辦法防止這種情況發生?
要將\\ uXXXX代碼設置回utf-8:
json_string.gsub!(/\\u([0-9a-z]{4})/) {|s| [$1.to_i(16)].pack("U")}
你可以通過猴子修補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
請注意,無法保證該補丁可以與未來版本的ActiveSupport一起使用。 撰寫這篇文章時使用的版本是3.1.3。
如果你深入挖掘源代碼,你最終會得到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
各種gsub
調用正在強制非ASCII UTF-8到您所看到的\\uXXXX
表示法。 十六進制編碼的UTF-8應該是處理JSON的任何東西都可以接受的,但你總是可以對JSON(或修改后的JSON轉發器中的猴子補丁)進行后處理,以便在必要時將\\uXXXX
表示法轉換為原始UTF-8。
我同意強制JSON為7bit-clean有點假,但你去了。
簡答:不。
字符沒有使用Rails2.3.11/Ruby1.8
的其他方法轉義為unicode,因此我使用了以下內容:
render :json => JSON::dump(obj)
這是正確的編碼。 JSON不requre轉義Unicode字符,但它是常見的JSON庫以產生僅包含7位ASCII字符輸出,以避免在運輸任何潛在的編碼問題。
任何JSON解釋器都可以使用該字符串並重現原始字符串。 要查看此操作,只需在瀏覽器的位置欄中輸入javascript:alert("ok\é")
即可。
渲染:如果對象不是字符串,json將在對象上調用.to_json。 您可以通過以下方式避免此問題:
render :json => JSON.generate(obj)
這將直接傳遞一個字符串,因此避免調用ActiveSupport的to_json。
另一種方法是覆蓋您正在序列化的對象上的to_json,因此在這種情況下,您可以執行以下操作:
class Foo < ActiveRecord::Base
def to_json(options = {})
JSON.generate(as_json)
end
end
如果您使用ActiveModelSerializers,您可以通過覆蓋序列化程序中的to_json來解決此問題:
# controller
respond_with foo, :serializer => MySerializer
# serializer
attributes :bar, :baz
def to_json(options = {})
JSON.generate(serializable_hash)
end
我有一個非常棘手的方法來解決這個問題。 好吧,如果to_json
不允許你擁有正確的代碼,那么你可以直接嘗試寫:
render text: tags
render json: tags
或render json: tags.to_json
將始終自動傳輸編碼樣式,但如果使用render text:tags
,則字符串將保持原樣。 我認為jQuery仍然可以識別數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.