I want to deep copy a json object in Ruby. However when I call clone the json object it doesn't seem to do a deep copy. Is it possible to or am I doing something wrong. Here is the relevant snippet of code of what I am doing now:
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
The error for me occurs because of the decode calls. The first decode call already decodes the object, and the second one tries to decode the same data again, which errors out in the second send call because at that point the data is gibberish.
How do I deep copy that json object?
JSON is merely text - and in this case it is assumed that the object can round-trip through JSON serialization.
Thus the simplest approach to go
Object->JSON(Text)->Object
to obtain a true deep clone; alternatively, deserialize the JSON twice (once for the deep clone, as the two deserializations produce in dependent object graphs). Note that Object here is not JSON, but merely the deserialized representation (e.g. Hashes and Arrays) of the data as a standard Ruby objects.As noted,
clone
does not do this serialization/deserialization step, but merely ascribes to shallow Object#clone semantics (actually, there is no Hash#clone, so it uses Object#clone's implementation directly):