2013-04-05 162 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引擎。