2016-06-23 6 views
8

Ich habe Probleme mit Sonderzeichen, wenn ich einen Hash in eine JSON-Zeichenfolge umwandle.to_json konvertiert keine Sonderzeichen in den Unicode-Stil

Alles funktioniert mit Ruby-2.0/Rails 3.2.21 in Ordnung, das heißt,

puts "“".to_json 
#"\u201c" 

Aber Ruby 2.3.0/Rails 4.2.5.1 I

bekommen
puts "“".to_json 
#"“" 

Gibt es eine Möglichkeit um Ruby 2.3.0 zu zwingen, Sonderzeichen in Unicode Style Strings umzuwandeln (\uXXXX)?

Bemerkung:

Beachten Sie, dass in Ruby 2.3/Rails 4, erhalten wir

"“".to_json.bytesize == 5 #true 

jedoch in 2.0 erhalten wir

"“".to_json.bytesize == 8 #true 

So klar ist es der String selbst, das ist anders , nicht verschiedene Ausgabeformate.

+1

Sie vergleichen die Implementierung verschiedener Ruby-Versionen. Würde es Ihnen etwas ausmachen, zu erklären, was das eigentliche Problem ist, das Sie zu lösen versuchen? – mudasobwa

+0

Ich vergleiche was? Dies hat nichts mit verschiedenen Puts-Implementierungen zu tun. Siehe "" .to_json.bytesize == 5 für 2.3 aber "" ".to_json.bytesize == 8 für 2.0 – Ingo

Antwort

5

❤ I Rails (nur ein Scherz.)

In Rails3 ein hilarious method war UTF-8 in JSON zu beschädigen. Rails4, danke DHH, von diesem Nachteil befreit.

Ganz gleich, ob man die Zeit zurück Maschine will, ist der einfachste Weg ::ActiveSupport::JSON::Encoding#escape monkeypatch:

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 

robustere Lösung zu verderben das Ergebnis wäre:

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" 

ich konnte kaum verstehe, warum jemand dies absichtlich tun möchte, aber die Lösung ist hier.

Verwandte Themen