JSON 到 ActiveRecord(反序列化)

JSON to ActiveRecord (deserialize)

我正在使用 Ruby、Grape 和 ActiveRecord 构建网络 API。来自 ASP.NET Web API 我习惯于将模型从 JSON 自动绑定到 class 对象,然后可以使用 Entity Framework 保存该对象。我一直在搜索一下,看看在使用 ActiveRecord 时是否有类似的东西,但没有发现任何让我觉得我遗漏了一些非常明显的东西。将 JSON 反序列化为 ActiveRecord 模型的最佳方法是什么?

更新

Matts 回答对简单类型非常有效,但是当我有关联时,我收到以下错误:ActiveRecord::AssociationTypeMismatch:预期连接器(#70297711668780),得到哈希(#70297701477140)

这是我的代码 运行

class Card < ActiveRecord::Base
   has_many    :connectors, autosave: true
end

class Connector < ActiveRecord::Base
   has_one  :card
   has_one  :connected_card, :class_name => "Card", :foreign_key => "connected_card_id"
end

json = "{\"id\":\"1\", \"connectors\": [{\"id\": 1, \"card_id\":1}]}"
card = Card.new(ActiveSupport::JSON.decode(json))

您可以使用来自 ActiveSupport 的标准 JSON 解码,这将为您提供一个哈希值。

然后您需要从该散列构建一个新的 ActiveRecord 对象。

my_object = Foo.new(ActiveSupport::JSON.decode(some_json))

如果您希望它保存在一行中,请将 new 换成 create

在您的模型中 Card 您已经创建了一个名为连接器的关联。这是一个 ActiveRecord::Relation 方法,它需要来自 class Connector 的一堆模型。否则,您正在传递一个哈希数组。

{"id"=>"1", "connectors"=>[{"id"=>1, "card_id"=>1}]}

在你的 #new 方法中,它变成了这样的东西:

Card.new(id: 1, connectors: [{id: 1, card_id: 1}])

到达那里后,连接器数组应填充连接器实例,而不是散列。这就是失败的原因。

你有两个选择。首先是重命名控制器中 before_action 中的键并使用嵌套属性:

class Card < ActiveRecord::Base
  has_many :connectors
  accepts_nested_attributes_for :connectors
end

class CardsController < ApplicationController
  before_action :set_nested

  private
  def set_nested
    params["connectors_attributes"] = params.delete("connectors")
  end
end

另一种选择是在模型中创建回调以从哈希创建对象。

class Card < ActiveRecord::Base
  def initialize(params={})
    params["connectors"] = params["connectors"].map {|connector| Connector.new(connector)}
    super(params)
  end
end

以上任何一项都将满足您的需求。 IMO 最好的是第一个,因为你不会重新定义 ActiveRecord#Methods