Question Rodrigo Werneck · Dec 15, 2023

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

Julius Kavay · Dec 15, 2023

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"" }
}
}
0
Enrico Parisi  Dec 16, 2023 to Julius Kavay

@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

0
Rodrigo Werneck  Dec 18, 2023 to Enrico Parisi

@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,

0
Brett Saviano · Dec 18, 2023

@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)
}
0