JsonSerializable classes

In many cases it is required to pass structured information between sessions . One sample is to pass parameter objects for a Business Task or Business Entity method from the client to the AppServer. A second sample is to transfer the required data for a KendoGrid from the AppServer to the Client (Browser) to render a Web User Interface.

Object serialization is used to transport the data members of an object instance to another session. Object deserialization is used to render a new object instance in the target session with the same data member values as the original object instance in the source session. OpenEdge supports object serialization between OpenEdge clients and the OpenEdge AppServer since OpenEdge 11.4 only.

For being compatible with less recent OpenEdge versions Consultingwerk and support object serialization with a broader set of AppServer clients, the SmartComponent Library provides XML and JSON serialization.

The following code snippet shows the definition of a JsonSerializable class including a property definition in OpenEdge 11 (or newer). 

JsonSerializable class definition
CLASS Consultingwerk.SmartComponentsDemo.OERA.Sports2000.ShipOrderParameter

    INHERITS JsonSerializable: 

    {Consultingwerk/JsonSerializableProperty11.i Instructions CHARACTER} .

To be compatible with XML serializable (typically used on OpenEdge 10.2B only) the class definition need to be tweaked to alternatively inherit from the XmlSerializable clss. The code below shows how to define a class that can switch between XML and JSON serialization. The SerializationType is defined in the products.i file shipped with the framework.

Alternative class definition for XML or Json srialization

USING Consultingwerk.* FROM PROPATH .
USING Progress.Lang.*  FROM PROPATH .

CLASS Consultingwerk.SmartComponentsDemo.OERA.Sports2000.ShipOrderParameter 
&IF "{&FrameworkSerializationType}" EQ "XML" OR PROVERSION
    INHERITS XmlSerializable
    INHERITS JsonSerializable

    {Consultingwerk/JsonSerializableProperty.i Instructions CHARACTER} .

The properties (data members) are defined using include files with the property name and datatype as parameters. Additional definition such as the initial value can be added as an optional third parameter typically in double quotes.

Note, that EXTENT fields (arrays) are considered a separate datatype and the EXTENT is provided as part of the datatype:

Property definition extended
    {Consultingwerk/JsonSerializableProperty.i ArrayProperty "CHARACTER EXTENT"} .

Please note in the above samples the difference between the definitions of the serializable properties. The include file JsonSerializableProperty.i does provide functionality for XML and JSON serialization. The JsonSerializableProperty11.i does only provide JSON serialization.

In the constructor of the serializable class it is required to call the AddSerializableProperties () method to provide the serialization routines the list of serializable property names. As the ABL does only support reflection since OpenEdge 11.6 it required to build the list of serializable properties as compile time.

Constructor of serializable class
    Purpose: Constructor for the ShipOrderParameter class                                                                    
CONSTRUCTOR PUBLIC ShipOrderParameter ():
    SUPER ().

    THIS-OBJECT:AddSerializableProperties ("{&SerializableProperties}":U) .


Sample serialization and deserialization


Variable definition for sample
DEFINE VARIABLE oParameter    AS ShipOrderParameter NO-UNDO.
DEFINE VARIABLE oSerializable AS ISerializable      NO-UNDO.

The following code creates an instance of a serializable class and assigns values to the properties. By calling into the Serialize() method a LONGCHAR representing the state of the object is returned. This JSON String can be passed to a different session or get stored in a database record (CLOB) or a file (xyz.json).

Serialization sample
oParameter = NEW ShipOrderParameter ().

    oParameter:OrderNum     = 1
    oParameter:ShipDate     = TODAY
    oParameter:SalesRep     = "BBB":U
    oParameter:Instructions = "Ship all at once!":U

lcParameter = oParameter:Serialize ().


MESSAGE "Serialized object:":U SKIP
        STRING (lcParameter)

To recreate an instance of the serializable class the JSON string (LONGCHAR) is passed to the DeserializeInstance() method of the Consultingwerk.Serializable class which returns an object reference of type ISerializable. This reference can be casted to the ShipOrderParameter class so that it is possible to access the properties again as shown in the sample below.

Deserialization sample
oSerializable = Serializable:DeserializeInstance (lcParameter).

ObjectAssert:TypeOf (oSerializable, "Consultingwerk.SmartComponentsDemo.OERA.Sports2000.ShipOrderParameter":U).

oParameter = CAST (oSerializable, ShipOrderParameter).

MESSAGE "Object prperties.":U SKIP
        "OrderNum:":U oParameter:OrderNum SKIP
        "ShipDate:":U oParameter:ShipDate SKIP
        "SalesRep:":U oParameter:SalesRep SKIP
        "Instructions:":U oParameter:Instructions

Serializing references of List or GenericList types

When properties of the serializable class are references to set types, it is required to create an object instance of the referenced set type in the constructor or the serializable class as the deserialization process is not able to determine the required set type itself from the JSON arrays used to serialize the set. 

Create List instance in constructor
THIS-OBJECT:SomeItems = NEW ListSomeItem () .

A sample for this can be seen in the class “Consultingwerk.Web.Kendo.Grid.KendoGrid”.