Question
· Apr 7

How to convert persistent object to dynamic object

Hi devs!

Suppose I have an instance of a persistent class:

Set person = ##class(dc.Sample.Person).%OpenId(1)

Class is an ancestor of %JSON.Adapter.

How can I convert it to dynamic object with the properties that person.%JSONExport() provides?

{"Name":"Elon Mask","Title":"Associate Accountant","Company":"InterSystems","Phone":"799-933-5569","DOB":"1926-12-11"}

Couldn't find a right method. 

set dynObj = ##class(%ZEN.Auxiliary.altJSONProvider).%ObjectToAET(person) works, but adds id and classname, which I don't want to be added:

zw dynObj
dynObj={"_class":"dc.Sample.Person","_id":1,"Name":"Elon Mask","Title":"Associate Accountant","Company":"InterSystems","Phone":"799-933-5569","DOB":31390}  ;

Thoughts?

Product version: IRIS 2025.1
Discussion (16)5
Log in or sign up to continue

not just Sample.Person but also Sample.Address,
or whatever serial class you refer to require %JSON Adaptor.
then

set person=##class(Sample.Person).%OpenId(3)
>set sc=person.%JSONExportToString(.Jperson)
set zjson={}.%FromJSON(Jperson)
ZWRITE
Jperson="{"LIMIT":103,"Name":"O'Rielly,Xavier E.","SSN":"331-77-5308","DOB":"1957-05-26","Home":{"Street":"8757 Elm Place","City":"Miami","State":"FL","Zip":"92027"},"Office":{"Street":"413 First Drive","City":"Miami","State":"NH","Zip":"83830"},"Age":67,"RowVer":0}"
person=<OBJECT REFERENCE>[2@Sample.Person]
sc=1
zjson=<OBJECT REFERENCE>[13@%Library.DynamicObject]

and there is your dynamic object

Wow, @Robert Cemper ! Thank you as usual! 

But 3 lines. Could it be a one command by any chance? :)

I compete with the following:

/// Get JSON for a person with a given id

ClassMethod personsidGET(messageRequest As dc.Sample.v3rest.requests.personsidGET) As %Status

{

 Set person = ##class(dc.Sample.Person).%OpenId(messageRequest.pathid)

 set stream=##class(%Stream.TmpCharacter).%New() 

 d person.%JSONExportToStream(.stream)

 return stream

}

This works, but with an unnecessary "to stream, out of stream" exercise IMHO.

OK

To Stream needs 1 line 2 statements
 

ClassMethod personsidGET(messageRequest As dc.Sample.v3rest.requests.personsidGET) As %Stream.Object
{
 set stream=##class(%Stream.TmpCharacter).%New(),sc=##class(dc.Sample.Person).%OpenId(messageRequest.pathid).%JSONExportToStream(.stream)
 return stream
 }

To String is shorter (just 1 statement) as you don't need to initialize %String)

ClassMethod personsidGET(messageRequest As dc.Sample.v3rest.requests.personsidGET) As %String
 do ##class(dc.Sample.Person).%OpenId(messageRequest.pathid).%JSONExportToString(.string)
 return string
{

Yes. But you cannot return String in this method - either dynamic object, or Stream object.

BTW, I’d even expect this functionality over %JSON.Adapter, as there is an option to import (construct) persistent from dynamic in it:

Set person=##class(dc.Sample.Person).%New()

do person.%JSONImport(dynamicPerson)

But person.%JSONExport() does JSON string into device. Would be wonderful to have:

D person.%JSONExport(.dynobj)

I know this has already been answered several ways, but let's not overlook embedded SQL as an option.

&sql(select JSON_OBJECT('Name':Name,'Title':Title,'Company':Company,'Phone':Phone, 'DOB':DOB) INTO :person WHERE ID = 1)
set personobj = {}.%FromJSON(person)

This can get a little unruly for tables with a lot of columns, but if you're wanting to pick out certain specific columns or customize the JSON field names, this approach gives you that flexibility.