使用ActiveRecord对MySQL JSON字段中的键进行符号化

时间:2019-02-15 12:30:58

标签: mysql ruby-on-rails json activerecord

我的一个模型中有一个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" }

1 个答案:

答案 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