%JSON.Adaptor with class that inherit from %ListOfObjects
I was trying the %JSON.Adapter backport to cache and try it also in IRIS and i found a kind of an issue regarding to export and object to json that is an inheritance of %ListOfObjects
If we have a list of elementtype of and object and then we try to export this to a json we get this json instead of a correct json.
exported json:
{
"ElementType":"test.element",
"Size":"1"
}
Json that we want:
[
{
"field1":"testField1",
"field2":"testField2"
}
]
Test classes:
Class test.elementList Extends (%ListOfObjects, %ZJSON.Adaptor){
/// The type (class name) of the elements stored in the collection. Parameter ELEMENTTYPE = "test.element";
}Class test.element Extends (%RegisteredObject, %ZJSON.Adaptor){
Property field1 As %String [ InitialExpression = "testField1" ];
Property field2 As %String [ InitialExpression = "testField2" ];
}Class test.Main Extends %RegisteredObject
{
ClassMethod Run()
{
Set elem = ##class(test.element).%New()
Set elemList = ##class(test.elementList).%New()
Do elemList.Insert(elem)
Do elemList.%JSONExportToString(.json)
Do ##class(%ZJSON.Formatter).%New().Format(json)
}
}I could fix it overwritting the %JSONExportToString in the elementList class in order to loop over elements and so on...but can be possible to fix this in IRIS? or is there any other solution?
Thanks !
Comments
Just to verify if this is a %JSON specific problem I added also %XML.Adaptor to the classes.
And there is a similar problem: %ListOfObjects seems to be the bad guy.
{"ElementType":"Test.element","Size":1}
Do elemList.XMLExport()
<elementList><ElementType>Test.element</ElementType><Size>1</Size></elementList>
zw elemList
elemList=2@Test.elementList ; <OREF>
+----------------- general information ---------------
| oref value: 2
| class name: Test.elementList
| reference count: 2
+----------------- attribute values ------------------
| Data(1) = ""
| ElementType = "Test.element"
| Oref(1) = "1@Test.element"
| Size = 1 <Set>
+-----------------------------------------------------
With a small extension, you may get closer to your result.
What you expect is a JSON Array, but %JSONExport... works on data OBJECTS, not on data TYPES { same as XMLExport() }
So I have created a small wrapper object:
Class Test.javier Extends (%RegisteredObject, %JSON.Adaptor)
{ Property wrap As Test.elementList(%JSONFIELDNAME = " "); }extending Test.Main:
{ClassMethod Run() {
Set elem = ##class(Test.element).%New()
Set elemList = ##class(Test.elementList).%New()
Do elemList.Insert(elem)
#; Do elemList.%JSONExportToString(.json)
#; Do ##class(%ZJSON.Formatter).%New().Format(json)
#;; extended
set jav=##class(Test.javier).%New()
set jav.wrap=elemList
Do jav.%JSONExportToString(.json)
set json=$e($p(json,":",2,*),1,*-1) ; a little bit dirty
Do ##class(%ZJSON.Formatter).%New().Format(json)
} }
And here we go:
[
{
"field1":"testField1",
"field2":"testField2"
}
]
SAMPLES>
I don't know if i will prefer override the %JSONExportToString and %JSONExportToStream or wrapping but that dirty trick..
Class test.elementList Extends (%ListOfObjects, %JSON.Adaptor)
{
/// The type (class name) of the elements stored in the collection.
Parameter ELEMENTTYPE = "test.element";
/// Returns this object as a JSON Stream
Method %JSONExportToStream(ByRef objStream As %Stream.Object, %mappingName As %String = "") As %Status
{
#Dim objStream As %Stream.TmpCharacter = ##class(%Stream.TmpCharacter).%New()
Do objStream.Write("[")
For i=1:1:..Size
{
Do ..GetAt(i).%JSONExportToStream(.objStream, %mappingName)
If (i<..Size)
{
Do objStream.Write(",")
}
}
Do objStream.Write("]")
Return $$$OK
}
/// Returns this object as a JSON string
Method %JSONExportToString(ByRef jsn As %String, %mappingName As %String = "") As %Status
{
#Dim jsonElement As %String = ""
Set jsn = "["
For i=1:1:..Size
{
Set jsonElement = ""
Do ..GetAt(i).%JSONExportToString(.jsonElement, %mappingName)
Set jsn = jsn_jsonElement
If (i<..Size)
{
Set jsn = jsn_","
}
}
Set jsn = jsn_"]"
Return $$$OK
}
}