JSON Parser

This forum is meant for questions and discussions about the X# language and tools
jonhn
Posts: 86
Joined: Thu Feb 01, 2018 8:04 am
Location: New Zealand

JSON Parser

Post by jonhn »

I would like to export from a DBF to JSON, and also re-import from a JSON file.
There was some discussion here: https://www.xsharp.eu/forum/german/3157-vo-und-restapi which provides a lot of information, and there is a VO version (or maybe it is Vulcan) in the JSONparser.zip.

I have loaded it into VO and was intending to bring it to X# via the VOXporter but there are a couple of missing functions/methods.
Has anyone already fixed this up and brought into X# that they would share (or sell?)?

It seems that it is very close to what I am looking for.
The missing methods are:
fFileRead
fFileWrite
MsgInternalError
AScanSymbol
SafeCreateInstance
RemoveZeroDecimals

Thanks! Jonathan
Attachments
JSON.JPG
JSON.JPG (62.71 KiB) Viewed 1232 times
jsonparser.zip
(14.45 KiB) Downloaded 136 times
User avatar
SHirsch
Posts: 286
Joined: Tue Jan 30, 2018 8:23 am
Location: Germany

JSON Parser

Post by SHirsch »

If you want to use JSON in X# I recommand Newtonsoft. Very powerful and widely used.

Stefan
jonhn
Posts: 86
Joined: Thu Feb 01, 2018 8:04 am
Location: New Zealand

JSON Parser

Post by jonhn »

Thank you Stefan, it looks perfect.
A question: To use it in my X# application which I edit in the XIDE, I first need to import it to VS, right?

1) create new solution (Vo MDI/X# flavor) in VS
2) use Nuget manager to download and install the package...
3) ?
Can I then copy the code over to XIDE, along with the Newtonsoft.JSON DLLs and use it there? Or is there more to be done?

I'm unsure how to massage it into the XIDE if anyone has a hint, or can confirm the steps above are about right that'd be very helpful.
Thanks! Jonathan
User avatar
SHirsch
Posts: 286
Joined: Tue Jan 30, 2018 8:23 am
Location: Germany

JSON Parser

Post by SHirsch »

Hi Jonathan
you can download directly from github (link).
After unpacking and referencing the correct framework version (e.g. net45) you can use it in X#.
Stefan

If you need something from nuget you do not have to use VS. I prefer to download the correct version from nuget.org directly. You get a nupkg file. Rename this to zip, unpack and extract the dll you need.
jonhn
Posts: 86
Joined: Thu Feb 01, 2018 8:04 am
Location: New Zealand

JSON Parser

Post by jonhn »

Thanks Stefan, that's very helpful.
OK, when I compile it X# requests System.Runtime reference, Ver 6.0.0., but there is only Ver 4.0.0. in the GAC.
Maybe I'm calling the wrong functions. I'm declaring USING Newtonsoft.Json, and reading through this https://www.newtonsoft.com/json/help/ht ... aderWriter

Sorry to ask - (I am reading through the documentation slowly) but do you have a small sample of the syntax you could share, for example, to read self:oDCMLE1:textvalue, translate it to JSON and display it in self:oDCMLE2:textvalue?
Thanks, Jon
User avatar
SHirsch
Posts: 286
Joined: Tue Jan 30, 2018 8:23 am
Location: Germany

JSON Parser

Post by SHirsch »

I am using LINQ to JSON.
newtonsoft.com/json/help/html/LINQtoJSON.htm

You can create JSON file from every object. All its public properties will be inserted. You can use Attributes für converting, renaming or ignoring values. You can also create the JSON object manually (look at the samples).
For parsing the SelectToken method is very powerful. You can extract very easily the values you need.

from the samples converted to X#

Code: Select all

VAR o := Newtonsoft.Json.Linq.JObject.Parse("{'Stores': ['Lambton Quay','Willis Street'],'Manufacturers': [{'Name': 'Acme Co','Products': [{'Name': 'Anvil','Price': 50}]},{'Name': 'Contoso','Products': [{'Name': 'Elbow Grease','Price': 99.95},{'Name': 'Headlight Fluid','Price': 4}]}]}")

VAR name := (STRING)o:SelectToken("Manufacturers[0].Name")
// Acme Co

VAR productPrice := (Decimal)o:SelectToken("Manufacturers[0].Products[0].Price")
// 50

VAR productName := (STRING)o:SelectToken("Manufacturers[1].Products[0].Name")
// Elbow Grease
I don't know what is in your MLE1. But you can put it in JObject.Parse. If it fails the syntax is not correct. Inspect the exception to see where the error is. If syntax is OK, you can do: SELF:oDCMLE2:TextValue := o:ToString().

Stefan
jonhn
Posts: 86
Joined: Thu Feb 01, 2018 8:04 am
Location: New Zealand

JSON Parser

Post by jonhn »

Hi Stefan,

I'm back to this creating JSON project. I'm clearly missing something simple here -
The idea is to open a DBF and convert each record/field to JSON - it is kind of working but I'm not getting the structure or "" quite right.
I'm getting a list of all the fields, but the records are not differentiated. Are you (or anyone) able to point out the missing link please?

oServer := DbServer{"Schedule.dbf"}
oServer:gotop()

DO WHILE !oServer:Eof
vText := Newtonsoft.Json.Linq.JValue.CreateString( "HIREINV : "+ Trim(oServer:Hireinv))
aarray:Add( vText)
vText := Newtonsoft.Json.Linq.JValue.CreateString("DTSTART : "+Trim(oServer:DTSTART))
aarray:Add(vText)
vText := Newtonsoft.Json.Linq.JValue.CreateString("DTEND : "+Trim(oServer:DTEND))
aarray:Add(vText)
vText := Newtonsoft.Json.Linq.JValue.CreateString("ADDRESS : "+Trim(oServer:ADDRESS))
aarray:Add(vText)
vText := Newtonsoft.Json.Linq.JValue.CreateString("CUSTOMER : "+Trim(oServer:CUSTOMER))
aarray:Add(vText)
vText := Newtonsoft.Json.Linq.JValue.CreateString("PEOPLE : "+Str(oServer:PEOPLE,5,2))
aarray:Add(vText)
vText := Newtonsoft.Json.Linq.JValue.CreateString("HOURS : "+Str(oServer:HOURS,5,2))
aarray:Add(vText)

IF oServer:FLEXIBLE
vText := Newtonsoft.Json.Linq.JValue.CreateString("FLEXIBLE : "+"TRUE")
ELSE
vText := Newtonsoft.Json.Linq.JValue.CreateString("FLEXIBLE : "+"FALSE")
ENDIF

aarray:Add(vText)
oServer:Skip()
ENDDO

The result is below. The curly brackets are not around the records, and also the " " are not in the right places - there should be a pair around each : in each string.
[
"HIREINV : 143273",
"DTSTART : 2022-12-07T09:00:00",
"DTEND : 2022-12-07T11:00:00",
"ADDRESS : Newmarket",
"CUSTOMER : ARC BRANCH",
"PEOPLE : 2.00",
"HOURS : 1.16",
"FLEXIBLE : FALSE",
"HIREINV : 143407",
"DTSTART : 2022-12-07T15:00:00",
"DTEND : 2022-12-07T16:00:00",
"ADDRESS : 43 Maskell Street- St Heliers",
"CUSTOMER : ST HELIERS KIND",
"PEOPLE : 1.00",
"HOURS : 0.50",
"FLEXIBLE : FALSE",
"HIREINV : 143549",
"DTSTART : 2022-12-08T08:00:00",
"DTEND : 2022-12-08T09:00:00",
"ADDRESS : Hyundai; Marine Sports Centre; 8/10 Tamaki Drive;",
"CUSTOMER : UniServices @ HMSC",
"PEOPLE : 1.00",
"HOURS : 1.00",
"FLEXIBLE : FALSE"
]

Thanks for any suggestions!
User avatar
SHirsch
Posts: 286
Joined: Tue Jan 30, 2018 8:23 am
Location: Germany

JSON Parser

Post by SHirsch »

Hi John,

not tested, but gives you an idea

Code: Select all

VAR jRecords := JArray{}
DO WHILE !oServer:EOF
   VAR jRec := JObject{ OBJECT[]{2}{JProperty{"HIREINV", Trim(oServer:Hireinv)}, ;
                                                           JProperty{"DTSTART ", Trim(oServer:DTSTART)},;
                                                            /* add your fields, an set the number of items in the initializer */
                                                            } }
   /* you can also add items here, jRec:Add( JProperty{"name", <SOME VALUE>} ) */
   jRecords:Add(jRec)
   oServer:Skip(1)
END DO
VAR txt := jRecords:ToString()
Stefan
jonhn
Posts: 86
Joined: Thu Feb 01, 2018 8:04 am
Location: New Zealand

JSON Parser

Post by jonhn »

Yes, that works perfectly! Like magic really. :)
Thank you.
jonhn
Posts: 86
Joined: Thu Feb 01, 2018 8:04 am
Location: New Zealand

JSON Parser

Post by jonhn »

Hi again... With your suggestion I can save the JSON file to a file, and now I want to read it back in after a 3rd party has edited it.

To decode the JSON file it must be the same process in reverse?
I read the file into a string - (in this case I put it in the SELF:oDCMLE1:textvalue) - this works
Parse it into a JSON array - aSchedule := JArray.Parse(SELF:oDCMLE1:TextValue) - this works
change it to a string json := aSchedule:ToString() -this works

I'm stuck here - The below doesn't work - but I want to have an object I can loop through, extracting the fields of each record and then save to the dbf. I'm barking up the wrong tree.

Do I use the JArray and extract the objects, or a string?

Is it this kind of thing? (this does not work as I have it)
VAR o := Newtonsoft.Json.Linq.JValue.Parse(json)
VAR Invoice := (STRING)o:SelectToken("HIREINV[0]")
VAR START := (STRING)o:SelectToken("DTSTART[0]")

Or is it like the export example you provided, but in reverse?
Thank you.
Post Reply