Question
Vitaly Furman · Dec 14, 2020

Can %JSONExport export a Stream as part of a JSON-aware object?

Hello,

We are working with a vendor who only accepts JSON as payload. We are currently still on Cache/HealthShare, not IRIS. Since we have to send Continuity of Care Documents, this raises issues with Long Strings (some CCDs can be quite large and in addition to that, they have to be b64-encoded which increases their size even more).

My question is: if we were to go on IRIS and use %JSON.Adapter, storing the encoded Stream in an object's Stream property, would calling %JSONExport() on this object produce the desired JSON? Or would we have to call %JSONExportToStream()?

We need the answer in order to know whether to suggest that our client go on IRIS.

Product version: 
IRIS 2020.1
00
2 0 3 97

Replies

Standard class object properties have a limited string length but a property can contain a %Stream.GlobalCharacter oref which %JSON.Adaptor can export as a JSON string.

Another option is to create a %DynamicObject (%Library.DynamicObject) class object or a %DynamicArray (%Library.DynamicArray) class object instead of using a subclass of %JSON.Adaptor.  You can create a %DynamicObject/%DynamicArray is ObjectScript by using a JSON object/array literal as an ObjectScript literal.  The %FromJSON class method will create a %DynamicObject/%DynamicArray by importing JSON from a %Stream, file or device and the %ToJSON class method will export a %DynamicObject/%DynamicArray to a %Stream, file or device.

On IRIS, the %Set and %Get methods in %DynamicObject-s/%DynamicArray-s have been extended to take type keywords of the form "stream", "stream>base64", "stream<base64" which can transfer %DynamicObject string elements between unlimited length %Stream-s and include the ability to encode or decode Base64 during the transfer.  There are also type key words "string", "string>base64", "string<base64" which can set/get ObjectScript string values into/from %DynamicObject elements but ObjectScript strings are currently limited to a length of 3,641,144 characters.

So on IRIS you can do something like:
   Set DynObj = {"ID":23, "Name":"John Doe", "BirthDay":"1974-12-15"}
   Do DynObj.%Set("DataFile",DataOref,"stream>base64")
   Do DynObj.%ToJSON(OutputOref)
where DataOref is a class reference to a %Stream.FileBinary referencing the binary file containing data related to John Doe and where OutputOref is a %Stream.FileCharacter referencing the file that will contain JSON text.

Thank you for the answer. It does sound like upgrading to IRIS product line would resolve the issue. The extension of %Set and %Get is a nice addition; I did not know about that. That means, we can continue using Dynamic Objects at least for outbound JSON and use those Stream>base64 to the encoding in the %ToJSON() call rather than before.

In trying different things, I used Dynamic Objects to break the long string into chunks of at most 3,641,144 and store them as Dynamic Array elements. That allows to get the data out of Cache without hitting the the long string problem. This will solve our problem if the receiving system accommodates an array with multiple elements and re-assembles the string.

Hi Steve,

Thank you for the answer. It does sound like upgrading to IRIS product line would resolve the issue. The extension of %Set and %Get is a nice addition; I did not know about that. That means, we can continue using Dynamic Objects at least for outbound JSON and use those Stream>base64 to the encoding in the %ToJSON() call rather than before.

In trying different things, I used Dynamic Objects to break the long string into chunks of at most 3,641,144 and store them as Dynamic Array elements. That allows to get the data out of Cache without hitting the the long string problem. This will solve our problem if the receiving system accommodates an array with multiple elements and re-assembles the string.