【问题标题】:Read json serialised objects back from a file从文件中读回 json 序列化对象
【发布时间】:2013-04-21 15:46:12
【问题描述】:

我的目标是将一组对象序列化为一个文件以创建备份。我开始使用模型上的方法(在这里简化,假设我有两个 ActiveRecords foo 和 bar):

def backup(file, foo, bar)  
  file.write(foo.to_json(root: true))
  file.write(bar.to_json(root: true))  
end  

这给了我一个我想要的文件,在这种情况下有两条记录:

{"foo":{"Account_id":1,"Name":"F","created_at":"2013-04-16T10:06:19Z","id":1,"updated_at":"2013-04-20T11:36:23Z"}}  
{"bar":{"Account_id":1,"Name":"B","created_at":"2013-04-16T10:06:19Z","id":1,"updated_at":"2013-04-20T11:36:23Z"}}  

稍后我想读取该备份并重新实例化这些对象,然后可能会将它们持久化回数据库。我的目标是遍历文件检查每个对象的类型,然后实例化正确的对象。

我有部分逻辑,但还没有全部,我还没有弄清楚在实例化之前如何确定每个序列化对象的类型。我的恢复代码如下:

def restore(file)
  file.each_line do |line|  
    **<some magic that parses my line into objectType and objectHash>**
    case objectType
    when :foo
      Foo.new.from_json(objectHash)
      Foo.process
      Foo.save!
    when :bar
      Bar.new.from_json(objectHash)
      Bar.process
      Bar.save!
    end
  end
end  

我正在寻找的是“一些魔法”部分中的内容。我可以编写代码来直接解析该行以确定它是 foo 还是 bar,但我觉得可能有一些棘手的 Rails/Ruby 方法可以自动执行此操作。不幸的是,在这种情况下,谷歌不是我的朋友。我所能看到的只是网页请求中专注于 json 的页面,但没有以这种方式解析 json。是不是我遗漏了什么,或者我应该写代码直接拆分字符串并读取对象类型?

如果我确实编写代码来直接拆分字符串,我会写一些类似的内容:

objectType = line[/^{"(\w*)"=>(.*)}/, 1]  
objectHash = line[/{"(\w*)"=>(.*)}/, 2]

这非常难看,我确信有更好的方法(我仍在研究),但我不确定这甚至是正确的方法 v 有一些东西会自动查看 json 表示并从根值知道要实例化什么对象。

最后,使用 from_json 的实际实例化也不起作用,它没有填充我的 ActiveRecord 上的任何字段。它给了我 nil 参数,所以我认为解析语法不正确。

所以,这提出了三个问题:

  1. 有没有办法确定我刚刚丢失的是哪个对象,这样更干净?
  2. 如果没有并且我需要使用正则表达式,是否有一种语法可以一次性解析行的两个位,而不是我的两行具有相同的正则表达式?
  3. from_json 语法看起来不太好。我在这里缺少语法吗? (不再是一个问题 - 上面的代码是固定的,当它应该是 to_json 时,我使用的是 as_json,尽管文档对此相当不清楚......)

(注意:随着时间的推移进行编辑以澄清我的问题,并且因为我现在有一个有效的正则表达式(以前没有),但仍然不确定它是否非常优雅。)

更多信息——这里的问题之一,当我进一步深入研究时,as_json 实际上并没有给我 json——我在文件中拥有的是一个哈希,根本不是 json。此外,散列中 created_at 和 lastupdated_at 的值没有被引用 - 所以基本上这就是导致解析失败的原因。我已经确定我应该使用 to_json 而不是 as_json,尽管文档表明 as_json 应该可以工作。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3.2


    【解决方案1】:

    我不确定我是否完全理解您的方法,但我认为使用 JSON.parse() 会有所帮助。

    这里有一些很好的信息http://mike.bailey.net.au/2011/02/json-with-ruby-and-rails/

    这将帮助您将原始对象转换回哈希。

    【讨论】:

    • 我认为 JSON.parse() 是您在不尝试将其放回 ActiveRecord 时使用的,但使用新的 3.1 功能,您应该能够使用 object.from_json()反而。除了这样做的文档非常稀少。
    • 我已经更新了我的问题,以使其更清楚(希望)我在问什么,并且我的文件将以任意顺序存储多个对象,因此我需要查看每一行找出我正在读回并实例化的对象是什么
    • 我最终使用了 JSON.parse(),它工作正常。我很快就会写一篇关于我的代码最终是什么的文章。
    【解决方案2】:

    好的,所以我想我有一些可行的方法。我根本不相信它很优雅,但它给了我结果。稍后我会花一些时间尝试使其更清洁。

    代码如下所示:

    file.each_line do |line|
      objectType = line[/^{"(\w*)":(.*)}/, 1]
      objectJSON = line[/{"(\w*)":(.*)}/, 2]
      objectHash = JSON.parse(objectJSON)
      case objectType
      when 'foo'
        restoredFoo = Foo.new(objectHash.except('id', 'created_at', 'updated_at'))
        restoredFoo.created_at = objectHash['created_at']
        restoredFoo.updated_at = objectHash['updated_at']
        restoredFoo.save!
      end
      when 'bar'
        restoredBar = Bar.new(objectHash.except('id', 'created_at', 'updated_at'))
        restoredBar.created_at = objectHash['created_at']
        restoredBar.updated_at = objectHash['updated_at']
        restoredBar.save!
      end
    end
    

    注意事项:

    1. 我觉得应该有一种方法可以创建不是 JSON.parse 的对象,而是使用模型上的 from_json 方法。如果不这样做,我不确定 from_json 有什么用!!
    2. 我对 mass_assignment 很满意。我真的不想使用 :without_protection => true,尽管这是一个选项。我担心的是我确实希望将 created_at 和 updated_at 恢复原样,但我想要一个新的 id。我将为我的应用程序中的许多实体执行此操作,我真的不想最终复制代码中的 attributes_protected - 它似乎不是很干燥
    3. 我仍然很确定我的 reg exp 可以在一次调用中同时给我 objectType 和 objectJSON

    但话虽如此,它确实有效,这是向前迈出的一大步。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-19
      • 2015-04-03
      • 2020-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-10
      相关资源
      最近更新 更多