Class wwJsonSerializer

This class can serialize FoxPro objects, values, collections and cursors to JSON and deserialize JSON strings into FoxPro objects, values or collections. Arrays are supported only as members of objects - all lists should be expressed preferably as Collections.

The serializer supports complex nested structures and can also serialize (but not directly deserialize) FoxPro tables and cursors by way of a custom string syntax (cursor:AliasName). Objects returned are created dynamically on the fly with all arrays parsed into FoxPro collections.

The serializer can handle these FoxPro types:

  • Simple Values (strings, numbers, bools, dates, blob)
  • Objects - plain or nested
  • Arrays
  • Collections
  • Cursors (using special cursor:<cursorName> syntax)

The de-serializer can handle these JSON types:

  • Simple Values (string, number, bool, date, blob)
  • Objects - plain or nested
  • Arrays - returned as FoxPro Collections!

To serialize existing objects:

do wwJsonSerializer
loSer = CREATEOBJECT("wwJsonSerializer")
lcJson = loSer.Serialize(loObject)  && Objects, Values, Collections

To create objects and serialize:

loCustomer = CREATEOBJECT("Empty")
ADDPROPERTY(loCustomer,"lastname", "Strahl")
ADDPROPERTY(loCustomer,"firstname", "Rick")
ADDPROPERTY(loCustomer,"company", "West Wind")

*** Add a nested object
loAddress = CREATEOBJECT("EMPTY")  
ADDPROPERTY(loCustomer, "address", loAddress)  && Add as child to ^customer
ADDPROPERTY(loAddress, "street", "101 Nowhere Lane")
ADDPROPERTY(loAddress, "city", "Anytown")
ADDPROPERTY(loAddress, "zip", "11111")

loSer = CREATEOBJECT("wwJsonSerializer")
loSer.PropertyNameOverrides = "lastName,firstName"  && exact casing
lcJson = loSer.Serialize(loCustomer)

Important: FoxPro objects don't return property names in a case sensitive way, so by default all property names are serialized as lower case. If you need mixed case property names, you can use PropertyNameOverrides to override specific property names with custom casing.

Serialize a FoxPro Cursor or Table:

select * from customers into TCustomers
lcJson = loSer.Serialize("cursor:TCustomers")  && Tables/Cursors

You can also add a cursor as a nested property. The cursor serializes as an Array:

loCustomer = CREATEOBJECT("Empty")
ADDPROPERTY(loCustomer,"company", "West Wind")

select * from Orders where custId = lnOrderId INTO CURSOR TOrders
ADDPROPERTY(loCustomer,"orders","cursor:TOrders")   && creates JSON Array

Cursor Serialization

A Cursor is serialized into JSON as an Array of Objects and de-serialized from JSON as a FoxPro Collections of Objects.

However, you can use CollectionToCursor() to convert JSON collections back into a cursor by providing an open target cursor or table to import to.

To de-serialize:

loCustomer = loSer.DeserializeJson(lcJson)  && JSON Objects, Values, Arrays 
? loCustomer.lastname 
? loCustomer.address.city

Here's an example that demonstrates how wwJsonSerializer works when round-tripping data:

lcJson = '{ "id": 50445, "message": "Whooo hooo", ' +;
         '   "status": 10 , "entered": "2018-11-21T23:10:10Z", ' +;
         '   "address": { "street": "123 Timber Ln", "number": 32 } }'

loSer = CREATEOBJECT("wwJsonSerializer")
loResult = loSer.DeserializeJson(lcJson)

? loResult.Id       && 50444
? loResult.entered  && 11/21/2018 03:10 PM (local time)

? loSer.Serialize(loResult,.T.)

The code takes in a JSON string converts it to an object and then turns around and turns it back into formatted JSON which looks like this (formatted because of the .T. parameter):

{
  "address": {
    "number": 32,
    "street": "123 Timber Ln"
  },
  "entered": "2018-11-21T23:10:10Z",
  "id": 50445,
  "message": "Whooo hooo",
  "status": 10
}
Custom
  wwJsonSerializer

Class Members

MemberDescription

Deserialize

Deserializes a JSON string into a FoxPro value, object or wwCollection instance for arrays. This method uses .NET and the JSON.NET library.

Objects are created as new instances of EMPTY objects and passed back. Arrays are passed back as FoxPro Collection objects.

o.Deserialize(lcJson)

DeserializeCursor

o.DeserializeCursor(lcJson, lcReadWriteCursor)

FormatJson

o.FormatJson(lcJson)

MapPropertyName

o.MapPropertyName(@lcJson, lcOriginal,lcNewName)

Property

o.Property(loObject,lcProperty,lvValue)

Serialize

o.Serialize(lvValue, llFormat)

AssumeUtcDates

If set to .T. assumes that all dates in the data structure passed are UTC dates and the dates are not time adjusted for UTC time.

DefaultEmptyDate

FormattedOutput

When .T. causes the output to be pretty formatted with indentations for each object level.

This flag affects the behavior of the Serialize() method.

IgnoreDollarVars

PropertyExclusionList

PropertyNameCharacterFilter

Property name filter applied to properties that are dynamically created by the deserializer. Strips out invalid characters for FoxPro variable names.

Defaults to all alpha-numeric characters and _.

This property is internally set and generally you shouldn't mess with this value.

PropertyNameOverrides

TrimStringValues

If .T. trims all string values removing trailing spaces to minimize payload size on the wire.

Example

DO wwJsonSerializer && Load libs

*** Create a complex object
loCust = CREATEOBJECT("Empty")
ADDPROPERTY(loCust,"Name","Rick")
ADDPROPERTY(loCust,"Entered",DATETIME())

*** Create a nested object
ADDPROPERTY(loCust,"Address", CREATEOBJECT("Empty"))
ADDPROPERTY(loCust.Address,"Street","32 Kaiea Place")
ADDPROPERTY(loCust,"Number",32)

loSer = CREATEOBJECT("wwJsonSerializer")

*** Serialize into JSON
lcJson =  loSer.Serialize(loCust)

? lcJson
*{"address":{"street":"32 Kaiea Place"},"entered":"2012-05-12T03:55:35Z","name":"Rick"}

*** read back from JSON into an object
loCust2 = loSer.DeserializeJson(lcJson)

? loCust2.Name
? loCust2.Entered
? loCust2.Address.Street
? loCust2.Address.Number

You can also serialize cursors:

select * from customers ;
    into cursor TCustomers ;
    order by company

lcJson = loSer.Serialize("cursor:TCustomers")

Requirements

Assembly: wwjsonserializer.prg wwDotnetBridge.prg wwutils.prg wwapi.prg wwcollections.prg wwDotnetBridge.dll newtonsoft.json.dll

See also:

Class wwDynamic

© West Wind Technologies, 2023 • Updated: 12/05/22
Comment or report problem with topic