Ruby中的深拷贝JSON对象

时间:2013-09-06 01:11:08

标签: ruby ruby-1.9

我想深入复制Ruby中的json对象。但是,当我调用克隆json对象时,它似乎没有做深度复制。是否有可能或者我做错了什么。以下是我现在正在做的相关代码片段:

idFile = File.new(options[:idFile])
idFile.each_line do |id|
    jsonObj = getJson(id)
    copyObj = jsonObj.clone
    copyObj['details']['payload'] = Base64.decode64(copyObj['payload'])
    copyObj['key'] = 1
    jsonObj['details']['payload'] = Base64.decode64(jsonObj['payload'])
    jsonObj['key'] = 2
    send(copyObj)
    send(jsonObj)  #error here
end

def getJson(id)
    idData = getData(id)
    idJson = JSON.parse!(idData)
    idJson = idJson['request'][0]
    return idJson
end

由于解码调用,我发生了错误。第一个解码调用已经解码了对象,第二个解码调用再次尝试解码相同的数据,这在第二个发送调用中出错,因为此时数据是乱码的。
如何深度复制该json对象?

2 个答案:

答案 0 :(得分:2)

JSON只是文本 - 在这种情况下,假设对象可以通过JSON序列化进行往返。

因此,最简单的方法是Object->JSON(Text)->Object获得真正的深度克隆;或者,将JSON反序列化两次(一次用于深​​度克隆,因为两个反序列化在依赖对象图中产生)。请注意,此处的Object是不是 JSON,而只是数据的反序列化表示(例如Hashes和Arrays)作为标准Ruby对象。

# Standard "deep clone" idiom using an intermediate serialization.
# This is using JSON here but it is the same with other techniques that walk
# the object graph (such as Marshal) and generate an intermediate serialization
# that can be restored later.
jsonObj = getJson(id)
jsonObj["foo"] = "change something"
json = JSON.generate(jsonObj)
copyObj = JSON.parse(json)

# Or, assuming simple deep clone of original, just deserialize twice.
# (Although in real code you'd only want to get the JSON text once.)
jsonObj = getJson(id)
copyObj = getJson(id)

如上所述, clone不会执行此序列化/反序列化步骤,而只是归于shallow Object#clone semantics(实际上,没有Hash#clone,因此它使用了Object #cron的直接实现):

  

生成obj的浅拷贝 - 复制obj的实例变量,但不复制它们引用的对象。

答案 1 :(得分:0)

如果您只是想要对任意Ruby对象进行深层复制,请尝试使用deep_dive。

https://rubygems.org/gems/deep_dive