Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1

TOPIC:

JSON Parser 23 Nov 2022 01:28 #24544

  • jonhn
  • jonhn's Avatar
  • Topic Author


  • Posts: 66
  • I would like to export from a DBF to JSON, and also re-import from a JSON file.
    There was some discussion here: 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

    Please Log in or Create an account to join the conversation.

    JSON Parser 23 Nov 2022 08:12 #24545

    • SHirsch
    • SHirsch's Avatar


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

    Stefan

    Please Log in or Create an account to join the conversation.

    JSON Parser 24 Nov 2022 01:10 #24552

    • jonhn
    • jonhn's Avatar
    • Topic Author


  • Posts: 66
  • 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

    Please Log in or Create an account to join the conversation.

    JSON Parser 24 Nov 2022 08:35 #24553

    • SHirsch
    • SHirsch's Avatar


  • Posts: 261
  • 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.

    Please Log in or Create an account to join the conversation.

    JSON Parser 24 Nov 2022 10:33 #24556

    • jonhn
    • jonhn's Avatar
    • Topic Author


  • Posts: 66
  • 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 www.newtonsoft.com/json/help/html/readin...htm#TextReaderWriter

    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

    Please Log in or Create an account to join the conversation.

    JSON Parser 24 Nov 2022 13:14 #24558

    • SHirsch
    • SHirsch's Avatar


  • Posts: 261
  • 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#
    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

    Please Log in or Create an account to join the conversation.

    JSON Parser 07 Dec 2022 09:25 #24678

    • jonhn
    • jonhn's Avatar
    • Topic Author


  • Posts: 66
  • 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!

    Please Log in or Create an account to join the conversation.

    JSON Parser 07 Dec 2022 12:05 #24682

    • SHirsch
    • SHirsch's Avatar


  • Posts: 261
  • Hi John,

    not tested, but gives you an idea
    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

    Please Log in or Create an account to join the conversation.

    JSON Parser 08 Dec 2022 02:06 #24694

    • jonhn
    • jonhn's Avatar
    • Topic Author


  • Posts: 66
  • Yes, that works perfectly! Like magic really. :)
    Thank you.

    Please Log in or Create an account to join the conversation.

    JSON Parser 08 Dec 2022 10:56 #24702

    • jonhn
    • jonhn's Avatar
    • Topic Author


  • Posts: 66
  • 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.

    Please Log in or Create an account to join the conversation.

    JSON Parser 08 Dec 2022 13:54 #24704

    • SHirsch
    • SHirsch's Avatar


  • Posts: 261
  • Hi,

    if your json is an object ( {..} ) then

    VAR Invoice := (STRING)o:SelectToken("HIREINV")

    www.newtonsoft.com/json/help/html/SelectToken.htm

    Stefan

    Please Log in or Create an account to join the conversation.

    JSON Parser 09 Dec 2022 07:43 #24710

    • Sherlock
    • Sherlock's Avatar


  • Posts: 50
  • I wrote a JSON to import to DBSERVER,, way back.. hope this helps someone

    METHOD AppendJSON( oFSSource ) CLASS DBServer

    LOCAL lRetCode := FALSE AS LOGIC
    LOCAL cSource AS STRING
    LOCAL cPath AS STRING
    LOCAL oError AS USUAL
    LOCAL dwCurrentWorkArea AS DWORD
    LOCAL jp AS JsonParser
    LOCAL ja AS JsonArray
    LOCAL jo AS JsonObject
    LOCAL aDBStruct := {} AS ARRAY
    LOCAL aAllkeys := {} AS ARRAY
    LOCAL xx, yy, nPos AS DWORD
    LOCAL uValue AS USUAL

    #IFDEF __DEBUG__
    DBFDebug("Entering "+__ENTITY__)
    #ENDIF
    //
    SELF:lErrorFlag := FALSE
    //
    BEGIN SEQUENCE
    VODBSelect( wWorkArea, @dwCurrentWorkArea )
    IF SELF:Notify( NOTIFYINTENTTOMOVE )
    IF IsInstanceOfUsual( oFSSource, #FileSpec )
    cSource := oFSSource:FullPath
    ELSE
    cSource := oFSSource
    IF At2( "\", cSource ) == 0
    cPath := SELF:oFileSpec:FullPath
    cSource := SubStr3( cPath, 1, RAt2( "\", cPath ) ) + cSource
    ENDIF
    ENDIF
    //
    aDBStruct := SELF:DbStruct // Get structure array from DBF
    //
    jp := JsonParser{}
    IF jp:LoadFromFile( cPath+cSource ) // Read the JSON data, import to DBF
    //
    ja := jp:RootJson:ValAsArray // Get Root JSON array of records
    // JSON data types to check... now match to DBF data types
    // JsonType_String := 0 / JsonType_LongInt := 1 / JsonType_Real8 := 2 / JsonType_Float := 2
    // JsonType_Logic := 3 / JsonType_Null := 4 / JsonType_Object := 5 / JsonType_Array := 6
    //
    FOR xx := 1 TO ja:Size // 1 to All Json array records...
    jo := ja:GetJsonObject(xx) // Jo will be a Record, ie. "Prop_code TO "B_zzclean2" jo:Size = 42
    //
    IF SELF:APpend() // Append to the DBF the data from JSON data
    //
    aAllkeys := jo:AllKeys // All the keys is the FIELD names.
    //
    FOR yy := 1 TO ALen(aAllkeys)
    // ? aAllkeys[yy] , jo:GetJsonValue(aAllkeys[yy]):JsonType // String = 0 / Numeric = 1,2 / Logic = 3
    nPos := AScan(aDBStruct, {|a| a[DBS_NAME] == aAllkeys[yy]})
    IF nPos > 0
    //
    DO CASE
    CASE aDBStruct[nPos][ DBS_TYPE ] = "C" ; uValue := jo:GetString(aAllkeys[yy]) // DBF needs "C"har string format
    CASE aDBStruct[nPos][ DBS_TYPE ] = "D" ; uValue := SToD(StrTran(jo:GetString(aAllkeys[yy]),[-])) // DBF needs "D"ate YYYY-DD-MM
    CASE aDBStruct[nPos][ DBS_TYPE ] = "N" ; uValue := jo:GetFloat(aAllkeys[yy]) // DBF need "N"umeric could be float or Int style
    uValue := Round( uValue, aDBStruct[nPos][ DBS_DEC ]) // Take Json value and trim to DBF field length [ie. 123.00 Round( xxx, 0) = 123
    IF SLen(AsString(uValue)) > aDBStruct[nPos][ DBS_LEN ] // resolve 2.0 v 2 [ int ] // Length of "new" Json data, verse field length
    uValue := 0 // If it will not fit, zero it.. else a crash.
    ENDIF
    CASE aDBStruct[nPos][ DBS_TYPE ] = "L" ; uValue := jo:Getlogic(aAllkeys[yy]) // DBF needs "L"ogic Json data as TRUE or FALSE
    CASE aDBStruct[nPos][ DBS_TYPE ] = "M" ; uValue := jo:GetString(aAllkeys[yy]) // DBF needs "M"emo as string, we do not allow Arrays, even though memo allows
    ENDCASE
    //
    SELF:FIELDPUT(aAllkeys[yy], uValue ) // Have FIELD NAME and value... write it.
    ENDIF
    //
    NEXT
    ENDIF
    NEXT
    SELF:Commit() // Commit the full record the say 42 fields..
    SELF:Unlock() // Unlock that record, the APPEND locked it.
    //
    lRetCode := TRUE
    ENDIF
    IF lRetCode
    lRetCode := SELF:__ProcessConcurrency( TRUE )
    ENDIF
    SELF:Notify( NOTIFYFILECHANGE )
    siSelectionStatus := DBSELECTIONNULL
    ELSE
    lRetCode := FALSE
    SELF:__SetStatusHL ( #AppendSDF, __CavoStr( __CAVOSTR_DBFCLASS_INTENTTOMOVE_CAPTION ), ;
    __CavoStr( __CAVOSTR_DBFCLASS_INTENTTOMOVE ) )
    ENDIF
    __DBSSetSelect( dwCurrentWorkArea ) //SE-060527
    //
    RECOVER USING oError
    oHLStatus := SELF:__GenerateStatusHL( oError )
    oErrorInfo := oError
    //
    SELF:__ProcessConcurrency( FALSE )
    //
    __DBSSetSelect( dwCurrentWorkArea ) //SE-060527
    lRetCode := FALSE
    //
    END SEQUENCE
    //
    #IFDEF __DEBUG__
    DBFDebug("Leaving "+__ENTITY__, AsString(lRetCode))
    #ENDIF
    //
    RETURN lRetCode
    Phil McGuinness

    Please Log in or Create an account to join the conversation.

    • Page:
    • 1