2013-04-05 158 views
2

我有一個具有utf8mb4字符的JSON字符串。我首先解析JSON,然後將結果編碼回JSON。之後,我將生成的JSON保存到mysql數據庫。 (這是一個簡化的執行流程,爲什麼我首先解析JSON並將其編碼回去是真實存在的原因)。將utf8mb4字符串保存到mysql

問題是數據庫最終會放上一個JSON字符串的前綴,我把它放在第一個utf8mb4字符處。

這裏是我的代碼:

require 'json' 
require 'mysql2' 

TABLENAME = 'my_table' 

settings = { 
    :database => "my_database", 
    :host => "localhost", 
    :password => "my_password", 
    :username => "my_username" 
} 

@database = Mysql2::Client.new settings 
@json = %q({"test":"begin \ud83d\ude04\ud83d\udc4d\ud83d\udc4f\ud83d\udd14 end"}) 

begin 
    obj = JSON.parse @json 
rescue JSON::ParserError => e 
    @json.force_encoding 'utf-8' 
    encoded = @json.valid_encoding? ? @json : @json.encode!('utf-8', invalid: :replace, undef: :replace) 
    obj = JSON.parse encoded 
end 

q = "create table if not exists `#{TABLENAME}` (json text not null) engine=InnoDB default charset=utf8" 
@database.query q 

text = @database.escape JSON.generate obj 
q = "insert ignore into `#{TABLENAME}` (json) values('#{text}')" 
@database.query q 

q = "select * from `#{TABLENAME}`" 
rs = @database.query q 

rs.each {|r| 
    p r 
} 

輸出爲:

{"json"=>"{\"test\":\"begin "} 

我不知道爲什麼會這樣,我希望得到任何幫助!

+0

當您使用更簡單的非ASCII東西'é'或'μ'而不是表情符號時,它會起作用嗎? – 2013-04-05 02:59:16

+0

@ muistooshort感謝您的評論,我沒有意識到它與他們是MBB4字符有關。如果將\ u0428(西里爾文Ш)插入字符串中(切斷字符之前),則會成功保存。 – akonsu 2013-04-05 03:18:43

+0

我不得不玩弄'\ u'的東西一點點來發現它。 JavaScript似乎對他們感到滿意,Ruby 1.9.2並非如此。如果您不通過數據庫發送任何內容會發生什麼?或者,如果您使用二進制列類型而不是字符串類型? – 2013-04-05 03:24:30

回答

2

感謝@muistooshort幫助我找到一個方法來解決這個問題:

... 
settings = { 
    ... 
    :encoding => 'utf8mb4' 
} 
... 
q = "create table ... default charset=utf8mb4" 
... 

這僅適用於那些支持當然utf8mb4引擎。