How to clone dynamic objects?
How to clone dynamic objects more efficiently than using a serialization/desserialization approach (eg. Set objectB = {}.%FromJSON(objectA.%ToJSON()) ) ?
Why %DynamicObject could not extend %RegisteredObject and its %ConstructClone method (if not inherit it)?
Comments
A few lines of code and you have your own object cloner
Class DC.ObjCloner [ Abstract ]
{
/// obj: Cache/IRIS or a Dynamic(JSON) Object/// /// For simplicity, JSON-Types null, true, false, etc. are ignoredClassMethod Clone(obj)
{
if$isobject(obj) {
if obj.%IsA("%DynamicAbstractObject") {
if obj.%IsA("%DynamicObject") { setnew={},arr=0 } else { setnew=[], arr=1 }
set iter=obj.%GetIterator()
while iter.%GetNext(.key,.val) {
set:$isobject(val) val=..Clone(val)
do$case(arr, 1:new.%Push(val), :new.%Set(key,val))
}
quitnew
} else { quit obj.%ConstructClone(1) }
} else { quit"" }
}
}
@Julius Kavay , nice code.
But the point was "more efficiently than using a serialization/deserialization", with this code it takes more than 4 times as serialization/deserialization.
I think that using serialization/deserialization IS very efficient.
@Rodrigo Werneck , are you having performance issues? What makes you think serialization/deserialization is inefficient? Did you measure the performance in your use case?
Enrico
@Enrico Parisi, I did no measures. I just thought that doing like @Julius Kavay suggested should be more direct and more efficient. Perhaps his code takes more time because it runs in ObjectScript semi-interpreted code while internal methods like %ToJSON and %FromJSON seems to be in external C compiled code ($zu(210)?).
Thank you both,
@Rodrigo Werneck
I recommend you use an intermediary stream to avoid <MAXSTRING> errors with large JSON objects:
ClassMethod DuplicateDAO(dao As%DynamicAbstractObject) As%DynamicAbstractObject
{
Set strm = ##class(%Stream.TmpCharacter).%New()
Do dao.%ToJSON(strm)
Return##class(%DynamicAbstractObject).%FromJSON(strm)
}