我的一个模型中有一个JSON列,其中包含一个哈希数组
create_table "articles", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
t.string "title"
t.json "data"
end
当我在#data
中存储Ruby哈希时,ActiveRecords会负责将其转换为json并将其存储在数据库中。
article = Article.new(data: [{ some: "data" }])
article.save
article.reload.data
=> [{ "some" => "data" }]
但是,如您在上面的示例中看到的那样,当我从数据库读回字段时,键被转换为字符串(这很明显,因为它存储为JSON)。
我的问题是:ActiveRecord是否提供任何内置功能来将字符串键转换为符号?
我可以覆盖getter并在适当位置象征键,但是如果您有很多json字段,这将变得不便:
def data
_data = self[:data]
_data.each.with_index do |hash, idx|
_data[idx] = hash.symbolize_keys
end
_data
end
当您在同一数组中混合使用数据类型时,情况变得更加混乱,并且必须注意是否为哈希值...
# this would fail because String does not implement #symbolize_keys
article.data << "foo"
article.data << { bar: "test" }
答案 0 :(得分:-1)
如果是有效的哈希,有一种方法可以将字符串键转换为符号。
JSON.parse(article.reload.data,:symbolize_names => true)
此方法将递归地表示所有键。它不会保留符号和字符串的任何混合。
但是,如果您错过了数据类型,则还需要检查数组的元素是哈希还是字符串。您可以使用Kernel#eval
进行尝试:
def valid_hash?(string)
eval(string).is_a?(Hash)
rescue SyntaxError
false
end
eval
方法的更多详细信息是here