嵌套 JSON 到 Ruby class(有验证)

Nested JSON to Ruby class (with validation)

我有以下 JSON:

{
   "ordernumber":"216300001000",
   "datecreated":"2016-11-08T14:23:06.631Z",
   "shippingmethod":"Delivery",
   ...
   "customer":{
      "firstname":"Victoria",
      "lastname":"Validator"
   },
   "products":[
      {
         "sku":"ABC1",
         "price":"9.99"
      },
      ...
   ]
}

与相应的 Ruby classes 包括验证器:

class Task
  include ActiveModel::Model
  include ActiveModel::Serializers::JSON

  validates ..., presence: true
  ...
end

class Product
  include ActiveModel::Model
  include ActiveModel::Serializers::JSON

  validates ..., presence: true
  ...
end

class Customer
  include ActiveModel::Model
  include ActiveModel::Serializers::JSON

  validates ..., presence: true
  ...
end

我想做的是将 JSON 序列化为 Ruby class。问题是 Task class 已正确初始化。但是像 Customer 和 Product 这样的嵌套 classes 仍然是散列。 (一个任务有一个客户和多个产品)

示例:

json = %Q{{ "ordernumber":"216300001000", "datecreated":"2016-11-08T14:23:06.631Z", "shippingmethod":"Delivery", "customer":{ "firstname":"Victoria", "lastname":"Validator" }, "products":[ { "sku":"ABC1", "price":"9.99" } ] }}

task = Task.new()
task.from_json(json)

task.class
# => Task

task.products[0].class
# => Hash

如何使用 ActiveModel 执行此操作并验证嵌套 JSON? (我没有使用 Rails)

据我所知,ActiveModel::Model 带来了验证和其他方便的东西,但它没有带来处理此类关联问题的工具。你必须自己实现他的行为。

首先,我会使用 ActiveModel::Model 提供的内置初始化系统。然后我会定义 products=customer= 来获取属性并初始化适当的 类 的实例。并调用关联记录的验证。

class Task
  include ActiveModel::Model

  attr_reader :products, :customer

  # ...

  validate :associated_records_are_valid

  def products=(ary)
    @products = ary.map(&Product.method(:new))
  end

  def customer=(attrs)
    @customer = Customer.new(attrs)
  end

  private

  def associated_records_are_valid
    products.all?(&:valid?) && customer.valid?
  end
end

attributes = JSON.parse(json_str)
task = Task.new(attributes)

看这个话题:Is it possible to convert a JSON string to an object?。我现在不在电脑前 post 代码,但我认为这个答案可以解决你的问题。