如何从 ActiveSerializer 加载嵌套的 json?

How to load nested json from ActiveSerializer?

我想为 JSON import/export 系统开发方法。

举一个简单的例子,我们有一只带爪子的猫,我做了这个:

class Cat < ApplicationRecord
  has_many :paws

  def json_export
    json = self.to_json(include: :paws)
    File.open("some_file_name.txt", "w") { |file| file.puts json }
  end

  def self.json_import
    Cat.new.from_json(File.open("some_file_name.txt", "rb").read)
  end
end

# I put Paw code below FYI

class Paw < ApplicationRecord
 belongs_to :cat
end

文件中的 JSON 是:

{"id":1,"name":"Felix","paws":[{"id":1,"color":"red","cat_id":1}]}

但是当我 运行 json_import 我得到了那个错误:

ActiveRecord::AssociationTypeMismatch: Paw(#69870882049060) expected, got {"id"=>1, "color"=>"red", "cat_id"=>1} which is an instance of Hash(#47217074833080)

我在 'from_json' 的文档中找不到与我的问题相关的任何内容,而且我也没有成功找到相关资源。没有宝石有没有办法做到这一点? (不过,如果我需要的话,我会考虑的)。

您在 paws 键名上有问题,要解决使用键名 paws_attributes

看属性需要键名accepts_nested_attributes_for

您的 .txt 文件内容应该如下所示

{"id":1,"name":"Felix","paws_attributes":[{"id":1,"color":"red","cat_id":1}]}

解决方案:

json = self.to_json({include: :paws, as: :paws_attributes})

并添加自定义 as_json 方法之一,如下所述。

class Cat < ApplicationRecord
  has_many :paws
  accepts_nested_attributes_for :paws

  def as_json(options = {})
    hash = super(options)
    hash[options[:as].to_s] = hash.delete(options[:include].to_s) if options.key? :as
    hash
  end
  
  #OR

  #  if want to use custom key names
  def as_json(options = {})
    json = {id: id, name: name} # whatever info you want to expose
    json[options[:as].to_s] = paws.as_json if options[:as]
    json
  end
  
  ...

end