%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 !
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)
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 } }