Web Connection
Should be simple, but isn't (at least not for me)
Gravatar is a globally recognized avatar based on your email address. Should be simple, but isn't (at least not for me)
  Michael B
  All
  Feb 14, 2020 @ 03:10pm

Rick,

I am working on integrating a javascript charts script into an admin page of mine. I need to serialize a cursor in vfp to generate a json string like the one below. My question is, "Do I need to write some clever vfp code to construct an object and manually populate it with some loops, or should I be able to do this with some additionally clever use of:

loSerializer = Createobject("wwJsonSerializer")
lcSeries = loSerializer.Serialize("cursor:tcursor")

    drilldown: {
        series: [
            {
                name: "Chrome",
                id: "Chrome",
                data: [
                    [
                        "v65.0",
                        0.1
                    ],
                    [
                        "v64.0",
                        1.3
                    ],
                    [
                     ......

If you have the time, here's a link to a demo page - Demo - The 'drill down' feature of the chart is where i am having trouble - it is using that nested example above)

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Harvey Mushman
  Michael B
  Feb 14, 2020 @ 03:59pm

what does your cursor look like? It is going to drive how the JSON is created if automatically generated.

But I don't see any way to get that level of nesting from one cursor. I'm guessing the easy way is to manually create a Collection and Empty object with properties to get the nesting then convert to JSON.

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Rick Strahl
  Michael B
  Feb 14, 2020 @ 04:45pm

Cursor serialization will do just that: Serialize a single cursor. It'll not give you a nested structure - it gives you an object with an array of records basically.

If you need something more complex you need to construct an object with all the subobjects attached and then serialize that:

DO wwJsonSerializer

SELECT custId, Name, Company, Entered FROM guest WHERE SUBSTR(name,1,1) =  "D" INTO CURSOR TGuests
SELECT custId, Name, Company, Entered FROM guest WHERE SUBSTR(name,1,1)  = "T" INTO CURSOR TGuests2

loSer = CREATEOBJECT("wwJsonSerializer")

obj = CREATEOBJECT("EMPTY")

*** Simple property
loSer.Property(obj,"companyName","West Wind")

*** Add a cursor as a property (serializes as an array)
loSer.Property(obj,"guests", "cursor:TGuests")

*** Add a sub object
loSer.Property(obj,"subObject",CREATEOBJECT("EMPTY"))
loSubObject = obj.SubObject
loSer.Property(loSubObject, "name","Rick")
loSer.Property(loSubObject, "guests", "cursor:TGuests2")

lcJson = loSer.Serialize(obj, .t.)
_cliptext = lcJson

This results in:

{
  "companyName": "West Wind",
  "guests": [
    {
      "custid": "_0EG16KJ8N",
      "name": "Douglas Osborne",
      "company": "Stores Automated Systems, Inc",
      "entered": "2007-05-06T15:26:39.997Z"
    },
    {
      "custid": "_0EG16KJ8R",
      "name": "Dr. Michael Holger",
      "company": "SystemConsulting",
      "entered": "2007-05-02T15:26:39.997Z"
    },
    {
      "custid": "_0EG16KJ8S",
      "name": "Dan Freeman",
      "company": "Information Management Group",
      "entered": "2007-05-01T15:26:39.997Z"
    }
  ],
  "subObject": {
    "guests": [
      {
        "custid": "_0EG16KJ8M",
        "name": "Terry A. Voss",
        "company": "Computer Consulting",
        "entered": "2007-05-07T15:26:39.997Z"
      },
      {
        "custid": "_0EG16KJ8V",
        "name": "Thomas Jakober",
        "company": "3S System Software Support",
        "entered": "2007-04-28T15:26:39.997Z"
      }
    ],
    "name": "Rick"
  }
}

Note you can use ADDPROPERTY() instead loSer.Property() but this method automatically adds to the property name overrides so things are serialized in the proper case you provide.

You can also use the wwDynamic class to make this more natural.

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Michael B
  Rick Strahl
  Feb 15, 2020 @ 07:05am

Rick,

Thanks so much for your response. This is the clean solution I was hoping for, however its not working for me in my old, customized version of WWWC. I installed your latest on a fresh machine and tested the solution and sure enough it works. I tried updating wwJsonSerializer and the key dll's (wwdotnetbridge, Newtonsoft.Json.dll, wc.dll, wwipstuff and a few others...)

My old version runs with the ISAPI connector, and the working version runs with .net. Could that be the issue or is it relying on other ww classes? My app looks more like 5.63 than anything else. However, I have been updating prg's here and there as you send out updates.

Ugh.

Getting an error in FUNCTION WriteObject(loObject)

lnIndex = this.oPropertyNames.GetIndex(lcFieldName) Error: Property GetIndex is not found

Here's my implementation of your directions.

loSer = CREATEOBJECT("wwJsonSerializer")
drilldown = CREATEOBJECT("EMPTY")
loSer.Property(drilldown,"series",CREATEOBJECT("EMPTY"))
loSeriesObject = drilldown.series

loSer.Property(loSeriesObject, "name",ALLTRIM(tcursor2Summary.name))
loSer.Property(loSeriesObject, "id",ALLTRIM(tcursor2Summary.name))

loDataObject = drilldown.series
loSer.Property(loDataObject, "data", "cursor:tcursor2details")
lcJson = loSer.Serialize(drilldown, .t.)

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Michael B
  Michael B
  Feb 17, 2020 @ 05:54am

Rick - I am hoping you can give me some guidance here. I would love to upgrade my whole framework to latest release, but way too much customization to 'just do it'...

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Rick Strahl
  Michael B
  Feb 17, 2020 @ 08:15pm

Not sure without you stepping in and checking what the value and type of the oPropertyNames object is.

It should be a wwCollection object. If it's something else I'd suspect an old version perhaps?

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Michael B
  Rick Strahl
  Feb 18, 2020 @ 05:06am

Hi Rick,

You guessed it. oPropertyNames is null using the old version of wwJsonSerializer. When updating only wwjsonSerializer and debugging, llPropNames is .T. and is a collection. The oPropertyNames object looks like this. The first row in the array is 'colorbypoint' which I manually set to .T. in the method that sets up the collection to be serialized.

opropertynames (object)
- aitems (array)
----- aitems[1] "name"
----- aitems[2] "colorByPoint"
----- aitems[3] "data"
----- aitems[4] "series"
----- aitems[5] "data"

I tried another simple serialization in a different process method that looks like this.

select * from myDbf into cursor tcursor && 20 rows of data

loSerializer =Createobject("wwJsonSerializerSophio")

obj = CREATEOBJECT("EMPTY")

*** Simple property
loSerializer.Property(obj,"companyName","West Wind")

*** Add a cursor as a property (serializes as an array)
loSerializer.Property(obj,"shipping", "cursor:tcursor")

lcjson = loSerializer.Serialize(obj,.t.)

This causes the same Property GetIndex is not found.

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Rick Strahl
  Michael B
  Feb 18, 2020 @ 01:18pm

I don't know what to tell you. If the newer version works either use that one, or compare files and update the old one.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Michael B
  Rick Strahl
  Feb 18, 2020 @ 03:12pm

Can you tell me what files get used when serialize() is called? Is it more than wwjsonserializer.prg, wwdotnetbridge.dll, and Newtonsoft.Json.dll?

Is the serialize function relying on prgs like wwApi and or wwRequest? I think no.

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Rick Strahl
  Michael B
  Feb 18, 2020 @ 05:43pm

All the dependencies are listed at the top of the source files. Plus you need wwipstuff.dll and wwdotnetbridge.dll.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Michael B
  Rick Strahl
  Feb 19, 2020 @ 02:08pm

I got it figured out. I simply RTFM (in this case the section you mentioned at the top of the prg). Fortunately, there was only a single function in wwutils that conflicted with my platform. I had a function in my own myutils.prg named FormatString(). You did not have this back in the old days of 5.63 (as far as I can tell).

After a quick search, it seems you only use FormatString() a single time in all of your demos.

lcFilename = FormatString("WeblogBackup{0:yyyy-MM-dd}.zip",DATETIME())

Can you tell me if you are using this for more than that one example on a regular basis?

Gravatar is a globally recognized avatar based on your email address. re: Should be simple, but isn't (at least not for me)
  Rick Strahl
  Michael B
  Feb 20, 2020 @ 12:34pm

Yes I use it all the time... It's a .NET style formatting function. But it's not used inside of the framework at this point.

The demos don't use it because it's relatively new. IOW, it isn't going away, but you can override it by declaring your FormatString after the built in one.

+++ Rick ---

© 1996-2024