В моем контроллере следующие работы (отпечатки "oké" )
puts obj.inspect
Но это не делает (делает "ok\u00e9" )
render :json => obj
По-видимому, метод to_json
избегает символов Unicode. Есть ли возможность предотвратить это?
В моем контроллере следующие работы (отпечатки "oké" )
puts obj.inspect
Но это не делает (делает "ok\u00e9" )
render :json => obj
По-видимому, метод to_json
избегает символов Unicode. Есть ли возможность предотвратить это?
Если вы копаете источник, вы в конце концов придете к 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
, которое вы видите. Hex-кодированный UTF-8 должен быть приемлемым для всего, что обрабатывает JSON, но вы всегда можете отправлять JSON (или патч обезьяны в модифицированном escaper JSON), чтобы преобразовать нотацию \uXXXX
в необработанный UTF-8, если это необходимо.
Я бы согласился с тем, что заставить JSON быть чистым 7 бит немного фиктивным, но там вы идете.
Короткий ответ: нет.
Чтобы вернуть коды \uXXXX в utf-8:
json_string.gsub!(/\\u([0-9a-z]{4})/) {|s| [$1.to_i(16)].pack("U")}
Вы можете предотвратить это путем обезглавливания метода, упомянутого muu, слишком коротким. Поместите следующее в config/initializers/patches.rb(или аналогичный файл, используемый для исправления материала) и перезапустите процесс рельсов, чтобы изменения повлияли.
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.
Это правильная кодировка. JSON не требует, чтобы символы Unicode были экранированы, но для JSON-библиотек для вывода данных, содержащих только 7-битные символы ASCII, часто возникает проблема во избежание любых возможных проблем с кодированием в пути.
Любой интерпретатор JSON сможет использовать эту строку и воспроизвести оригинал. Чтобы увидеть это в действии, просто введите javascript:alert("ok\u00e9")
в свою панель браузера.
Символы не были экранированы в unicode с другими методами в Rails2.3.11/Ruby1.8
, поэтому я использовал следующее:
render :json => JSON::dump(obj)
render: 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 все еще может распознавать данные.