2013-08-05 25 views
8

Tôi gặp lỗi JSON::GeneratorError: source sequence is illegal/malformed utf-8 khi cố gắng chuyển đổi băm thành chuỗi json. Tôi tự hỏi liệu điều này có liên quan gì đến việc mã hóa hay không và làm thế nào tôi có thể làm cho to_json chỉ xử lý \ xAE như vậy?Vấn đề Ruby to_json có lỗi "invalid/malformed utf-8"

$ irb 
2.0.0-p247 :001 > require 'json' 
=> true 
2.0.0-p247 :002 > a = {"description"=> "iPhone\xAE"} 
=> {"description"=>"iPhone\xAE"} 
2.0.0-p247 :003 > a.to_json 
JSON::GeneratorError: source sequence is illegal/malformed utf-8 
    from (irb):3:in `to_json' 
    from (irb):3 
    from /Users/cchen21/.rvm/rubies/ruby-2.0.0-p247/bin/irb:16:in `<main>' 
+0

chỉ trong trường hợp bạn có nghĩa là 'chỉ coi nó như nó là', bạn có thể tăng gấp đôi thoát nó: {"description" => "iPhone \\ xAE"}. To_json => "{\" description \ ": \ "iPhone \\\ \ xAE \"} " –

Trả lời

13

\xAE không phải là một nhân vật có giá trị trong UTF-8, bạn phải sử dụng \u00AE thay vì:

"iPhone\u00AE" 
#=> "iPhone®" 

Hoặc chuyển đổi nó cho phù hợp:

"iPhone\xAE".force_encoding("ISO-8859-1").encode("UTF-8") 
#=> "iPhone®" 
13

Mỗi chuỗi trong Ruby có một mã hóa lớp phủ. Tùy thuộc vào các biến môi trường LANGLC_ALL môi trường của bạn, trình bao tương tác có thể đang thực thi và diễn giải chuỗi của bạn trong một mã hóa nhất định.

$ irb 
1.9.3p392 :008 > __ENCODING__ 
=> #<Encoding:UTF-8> 

(bỏ qua tôi đang sử dụng Ruby 1.9 thay vì 2.0, ý tưởng vẫn giữ nguyên).

__ENCODING__ trả về mã hóa nguồn hiện tại. Bạn cũng có thể nói UTF-8.

Khi bạn tạo các chuỗi chữ và thoát sử dụng byte (các \xAE) trong mã của bạn, Ruby đang cố gắng giải thích rằng theo mã hóa chuỗi:

1.9.3p392 :003 > a = {"description" => "iPhone\xAE"} 
=> {"description"=>"iPhone\xAE"} 
1.9.3p392 :004 > a["description"].encoding 
=> #<Encoding:UTF-8> 

Vì vậy, các byte \xAE ở phần cuối của bạn chuỗi chữ sẽ được cố gắng xử lý như một byte dòng UTF-8, nhưng nó không hợp lệ. Hãy xem những gì sẽ xảy ra khi tôi cố gắng in nó:

1.9.3-p392 :001 > puts "iPhone\xAE" 
iPhone� 
=> nil 

Bạn có thể cần phải cung cấp cho nhân vật đánh dấu đăng ký tại một mã hóa hợp lệ UTF-8 (hoặc sử dụng các nhân vật thực sự, hoặc cung cấp hai UTF-8 byte):

1.9.3-p392 :002 > a = {"description1" => "iPhone®", "description2" => "iPhone\xc2\xae"} 
=> {"description1"=>"iPhone®", "description2"=>"iPhone®"} 
1.9.3-p392 :005 > a.to_json 
=> "{\"description1\":\"iPhone®\",\"description2\":\"iPhone®\"}" 

Hoặc, nếu đầu vào của bạn là tiêu chuẩn ISO-8859-1 (tiếng Latin 1) và bạn biết điều đó chắc chắn, bạn có thể nói với Ruby để giải thích chuỗi của bạn như mã hóa khác:

1.9.3-p392 :006 > a = {"description1" => "iPhone\xAE".force_encoding('ISO-8859-1') } 
=> {"description1"=>"iPhone\xAE"} 
1.9.3-p392 :007 > a.to_json 
=> "{\"description1\":\"iPhone®\"}" 

Hy vọng nó giúp.

+0

Cảm ơn rất nhiều vì đã giải thích rõ ràng. Tôi đã không nhận thấy \ xAE không được mã hóa UTF-8 nhưng sử dụng thoát Javascript (http://www.charbase.com/00ae-unicode-registered-sign) – ccy

Các vấn đề liên quan