Skip to content

ValueTree - Advanced Use

ValueTrees, along with the ValueTreeSerializeParameter and ValueTreeDeserializeParameter commands, are used within web services to convert data between a variable of a known data type (simple, array, or struct) and a standard format (the ValueTree). Because the format of the ValueTree is known, it can be generically converted to XML or JSON.

This is an advanced technique, and these commands and the entire process have always been private. However, a number of developers have been working with these commands to create ways to serialize and deserialize data in their objects. As part of an effort to turn these into public interfaces, we have made changes to make these commands more robust and flexible. When used properly, these commands can perform powerful tasks.

As part of making these commands more robust, we have improved error checking and done a better job of initializing parameter values. To enhance flexibility, we now support serializing from and deserializing to variant complex data types. In particular, a struct or an array stored in a variant can be serialized and deserialized using the underlying data type. This makes it possible to create generic methods that can serialize and deserialize any data type.

Serializing to a ValueTree

When serializing to a ValueTree, you may use a variant type, and the variant’s underlying type will be used. The following two examples are equivalent:

ValueTreeSerializeParameter MyArrayOfStructs to MyValueTree
Move MyArrayOfStructs to vVariant
ValueTreeSerializeParameter vVariant to MyValueTree

Deserializing from a ValueTree

When deserializing, the destination data type must be known. If the destination data type is a variant, it must be initialized with an instance of the underlying type (probably an empty instance). The following two examples are equivalent:

ValueTreeDeserializeParameter MyValueTree to MyArrayOfStructs
tSomeStruct[] MyArrayOfStructs
Move MyArrayOfStructs to vVariant // this initializes the destination variable
ValueTreeDeserializeParameter MyValueTree to vVariant
Move vVariant to MyArrayOfStructs

Doing this within a single method provides little advantage. The power of using variants is that you can assign any variable to a variant, pass that variant as a parameter, and use this to create generic serialize and deserialize methods.

Example: Generic Serialization and Deserialization

The following shows how this could be used to write generic methods that can serialize and deserialize any object property to/from a ValueTree. That ValueTree could then be converted to XML or JSON and stored as needed, providing a mechanism for creating persistent objects.

Use ui
Use tValueTree.pkg

Struct tWinPoint
    DWord x
    DWord y
End_Struct

Object o1 is a cObject
    Property String psName "John"
    Property tWinPoint pPt
    Property tWinPoint[] ppts

    Function SerializeProp Handle hmProp Returns tValueTree
        tValueTree vt
        Variant Val
        Get hmProp to Val
        ValueTreeSerializeParameter Val to vt
        Function_Return vt
    End_Function

    Procedure Set SerializeProp Handle hmGetProp Handle hmSetProp tValueTree vt
        Variant val
        Get hmGetProp to Val
        ValueTreeDeSerializeParameter vt to Val
        Get hmSetProp to Val
    End_Function
End_Object

Procedure Test
    String sN
    tValueTree vt vts vtsa
    tWinPoint pt pt2
    tWinPoint[] pts pts2
    Variant vsa val

    Move 5 to pt.x
    Move 10 to pt.y
    Set pPt of o1 to pt
    Get psName of o1 to sN
    Get SerializeProp of o1 (RefFunc(psName)) to vt
    Move "xxxxx" to vt.sValue
    Set psName of o1 to "aa"
    Set SerializeProp of o1 (RefFunc(psName)) (RefProcSet(psName)) to vt
    Get psName of o1 to sN
    Move 100 to pt.x
    Move 200 to pt.y
    ValueTreeSerializeParameter pt to vts
    Set SerializeProp of o1 (RefFunc(pPt)) (RefProcSet(pPt)) to vts
    Get pPt of o1 to pt

    Integer i
    For i from 0 to 100
        Move pt to pts[i]
    Loop

    ValueTreeSerializeParameter pts to vtsa
    Set SerializeProp of o1 (RefFunc(pPts)) (RefProcSet(pPts)) to vtsa
    Move (ResizeArray(pts, 0)) to pts
    Get pPts of o1 to pts
End_Procedure

Send Test

See Also

What's New in DataFlex 2015 - 18.1