(no subject)

Page 1.0 of 2.44
1 2 > >> (Page 1 of 2)
  • svenjotec - 2019-12-03

    It's cleared.

     

    Last edit: svenjotec 2019-12-03
  • nothinrandom - 2020-03-06

    Hello Guys,

    I believe there's an issue with nested structs on all verions. For example:

    TYPE stDebugJson :
    STRUCT
    timestamp : JSONVAR;
    messageType : JSONVAR;
    //message : JSONVAR; //works fine with setting MaxLevel to 1
    message : stDebugMessageDetails; // missing end bracket
    END_STRUCT
    END_TYPE

    stDebugMessageDetails is just another type:
    TYPE stDebugMessageDetails :
    STRUCT
    message : JSONVAR;
    END_STRUCT
    END_TYPE

    The output looks like:
    {"debugMessageJson":{"timestamp":"2020-03-06T23:27:22.966Z","messageType":"DEBUG","message":{"message":"test22"}}

     

    Last edit: nothinrandom 2020-03-06
    • tvm - 2020-05-05

      I'll see if I can find some time to test this out.

       
  • schwi - 2020-04-12

    Hi,
    you should add (GPL_JSON.MAX_VALUE_SIZE) on this string.
    Because if bigger value sizes it runs into faulty parse.
    TYPE JSONNAMEVALUE :
    STRUCT
    Value: STRING(GPL_JSON.MAX_VALUE_SIZE); //value of the object at this level
    END_STRUCT
    END_TYPE

    Greetings

     
    • tvm - 2020-05-05

      good catch, I'll add that to future versions

       
  • jumax - 2020-05-05

    Hello, I have a problem parsing a JSON string and I need help.

    The string I receive:
    '[{"device_id":"1","pgt_id":"2","usertag":"3","hgl":"4","ls":"5","rs":"6","erg":"7"}]'

    The struct I devined:
    TYPE strPGTdataSet:
    STRUCT
    device_id :JSONVAR;
    pgt_id :JSONVAR;
    usertag :JSONVAR;
    hgl :JSONVAR;
    ls :JSONVAR;
    rs :JSONVAR;
    erg :JSONVAR;
    END_STRUCT
    END_TYPE

    The FB I call:
    ParseJSON(
    Execute:=xParseJSON,
    JSONString:= ADR(hTTPClient_0.httpResult.sContent),
    JSONStringSize:= SIZEOF(hTTPClient_0.httpResult.sContent),
    JSONVars:= ADR(NewJSONObj),
    NumberOfVars:= SIZEOF(NewJSONObj) / SIZEOF(JSONVAR)
    );

    The NewJSONObj always remains empty. I also tried to define the NewJSONObj as an array of struct like this:
    TYPE strPGToutputSet:
    STRUCT
    recordset :ARRAY [0..0] OF strPGTdataSet;
    END_STRUCT
    END_TYPE

    I don't know if you need more information to help. Also I'm new to CODESYS programming.

    Thank you!

     
    • kamilp-2097 - 2020-07-23

      Hello, have you managed to solve this case? I am struggling with the same issue.

      Thanks.

       
      • manuknecht - 2023-10-19

        I am aware that this thread is three years old, but I ran into the same issue and could not resolve it. Does anyone know what can cause this?

        Thanks in advance!

        Edit:
        After some more tinkering, I found the issue preventing proper parsing of the JSON string. For this the library function JSON_TO_STRUCT (FB) has to be adjusted from row 100. The original implementation is as follows:

        //Match name and array index.  Array index will be 0 if the current name:value is not part of an array
        IF MATCH_NAMES(JSONVars^[jsonvarindex].Names[nameindex], NameValue[obj_level-(nameindex-1)]) THEN   
            foundname:= TRUE;   //name in JSON string matches the local variable name
        ELSE
            foundname:= FALSE;  //name in JSON string does not match the local variable name, go to next name
            EXIT;
        END_IF
        

        This checks if a key in the struct is identical to the key currently being processed. However, as the EXIT statement is set in case of no matching name, the loop continues after a match and in the next cycle, the variable foundname will be overwritten again. Changing the code accordingly did the trick for me:

        //Match name and array index.  Array index will be 0 if the current name:value is not part of an array
        IF MATCH_NAMES(JSONVars^[jsonvarindex].Names[nameindex], NameValue[obj_level-(nameindex-1)]) THEN   
            foundname:= TRUE;   //name in JSON string matches the local variable name
            EXIT;
        ELSE
            foundname:= FALSE;  //name in JSON string does not match the local variable name, go to next name
        END_IF
        

        If this library is still being moderated, it would be interesting to know if this was an error in the code or if I am simply using it wrong?

         

        Last edit: manuknecht 2023-10-19
        • tvm - 2023-10-27

          I haven't had a lot of time to do anything with this for several months, but thanks for the input. It does look like a bug, I'll try to take a closer look at it next week.

           
          • manuknecht - 2023-10-30

            If you will tackle it again, here's another issue I discovered. The JSON string I want to parse contains some nested arrays and objects. It came to my attention, that proper parsing only works when the key-value pairs on the lowest level (inside arrays) are sorted alphabetically. Otherwise, the values can be assigned to the wrong keys. I didn't check the code further to find what causes this, but maybe you will have an idea?
            Otherwise it seems to do what it does, so thanks a lot for sharing!

             
            • tvm - 2023-10-30

              I think I have reproduced something like this, but it would be helpful if you can provide a test program, or at least a JSON string that demonstrates it.

               
              • manuknecht - 2023-10-31

                I'll attach a project to this message. I am using the HTTPClient library to read a JSON string through a HTTP request. I left you a sample string that I want to parse in the code to demonstrate the issue. You can see that the key-value pairs do not match up between the string and the JSON struct.
                Hope that helps.

                 

                Last edit: manuknecht 2023-10-31
                • tvm - 2023-10-31

                  I've released v 1.0.0.15 (link above). I tested your project as well as several of mine, with various different orders of the variables and it's working for me. The code on line 100 was correct, as far as how the FOR loop/EXIT worked, but I refactored some of that to make it easier to understand.

                   
                  • manuknecht - 2023-11-01

                    Thanks a lot for the update! So my project worked with the old version of the library for you? That is very strange. Need to check it from my side then.

                     
  • tvm - 2020-05-05

    Hi, I haven't had time to test it, but have you tried recordset :ARRAY [1..1] OF strPGTdataSet;

     
  • bnewman - 2023-10-27

    Will you please rerelease this under MIT or MPL2?

    GPL is a cancer.

     
    • tvm - 2023-10-27

      @bnewman as far as I'm concerned, it's released under the terms of "it's on the internet so people can do whatever the heck they want with it". I think I had to pick a license when I put it on here, but I don't actually know anything about GPL, nor do I care. Use it, modify it, copy it, put it in your own projects, contribute to it, credit me. Or not. Whatever you like.
      I just changed the licensing to both MIT and Unlicense. I honestly don't know the difference, but I hope that makes it easier for you.

       

      Last edit: tvm 2023-10-27
  • bnewman - 2023-10-27

    awesome! thank you sir.

     
  • uspenskiyan - 2024-04-04

    Hello. I have an error in JSON_TO_STRUCT when trying to get JSON from string: 'Check application name in GPL_JSON.APPLICATION_NAME'. But I didn't change my application name, it's still "Application". What's wrong?

     
    • tvm - 2024-05-02

      Check any of your JSONVARs. The Names variable contains an array of the variable name divided by level. For example, if the variable path is Application.Test_SingleVar_PRG.colour, then the array will contain
      [3] 'Application'
      [2] 'Test_SingleVar_PRG'
      [1] 'colour'

      The ApplicationLevel property should be the array index which contains 'Application', in this case 3. This is all figured out in the JSONVAR.FB_Init method.

      The other place to check is JSONVAR.VarName, which is the full instance path of the variable as a string. The string length is set in GPL_JSON.MAX_VAR_NAME, by default 150 characters. Maybe your path is longer than 150 characters and something is getting cut off?

       
  • maxkemmeren - 2024-05-01

    SOLVED SEE REPLIES

    NOT A BUG, Different thinking approach

    Hello,

    There is still a bug within the Json_TO_Struct FB. Within the method MatchAllLevels:

    The EXIT Statement was in the wrong place within the for loop. As the loop needs to be exited when a match is found. The bug caused the matchalllevels method to always feedback the value false due to the exit statement.

    When placing the exit after match is set to true the values are parsed into the struct.

    --------------------------------------OLD-----------------------------------------------------------
    FOR i:= 1 TO obj_level DO
    //Match name and array index. Array index will be 0 if the current name:value is not part of an array
    IF MATCH_NAMES(i_JSONVar.Names[i], NameValue[obj_level-(i-1)]) THEN
    MatchAllLevels:= TRUE; //name in JSON string matches the local variable name
    ELSE
    MatchAllLevels:= FALSE; //name in JSON string does not match the local variable name, go to next name
    EXIT;
    END_IF
    END_FOR

    --------------------------------------NEW-----------------------------------------------------------
    FOR i:= 1 TO obj_level DO
    //Match name and array index. Array index will be 0 if the current name:value is not part of an array
    IF MATCH_NAMES(i_JSONVar.Names[i], NameValue[obj_level-(i-1)]) THEN
    MatchAllLevels:= TRUE; //name in JSON string matches the local variable name
    EXIT;
    ELSE
    MatchAllLevels:= FALSE; //name in JSON string does not match the local variable name, go to next name
    END_IF
    END_FOR

     

    Last edit: maxkemmeren 2024-05-02
    • tvm - 2024-05-02

      The EXIT is in the correct place in the original, this is not a bug. The loop returns FALSE and exits on the first occurrence of a mismatch. If there are any mismatches, there is no point in evaluating the rest of the array. All levels must match for this method to return TRUE.

       
      • maxkemmeren - 2024-05-02

        OKay but then there must be another error, as after the change the functionblock read all the values into my local struct. Without the fix my local struct stayed empty all the time.

         
        • tvm - 2024-05-02

          If you can post an example I can test it here.

           
          • maxkemmeren - 2024-05-02

            sFileContentsWrite_Struct : ST_TEST;
            sFileContentsWrite_Struct_Json : ST_TEST_Json;

            sFileContentsRead_Struct_Json : ST_TEST_Json;
            sFileContentsRead_Struct : ST_TEST;

            sFileContentsWrite_Struct_Json.fReal.Number := sFileContentsWrite_Struct.fReal;
            sFileContentsWrite_Struct_Json.nInteger.Integer := sFileContentsWrite_Struct.nInteger;
            sFileContentsWrite_Struct_Json.sText.CharString := sFileContentsWrite_Struct.sText;
            sFileContentsWrite_Struct_Json.fLreal.Number :=sFileContentsWrite_Struct.fLreal;

            s_fbJsonParser(
            Execute := Execute,
            Abort := Abort,
            JSONString := ADR(JsonString),
            JSONStringSize := SIZEOF(JsonString),
            JSONVars := ADR(sFileContentsWrite_Struct_Json),
            NumberOfVars := SIZEOF(sFileContentsWrite_Struct_Json)/SIZEOF(JSONVAR),
            VariableArraySize := TRUE,
            Format := false,
            Busy => Busy,
            Done => Done,
            Aborted => Aborted,
            Error => Error,
            ErrorPosition => ErrorPosition,
            ComposeTime => ComposeTime);

            s_fbStructParser(
            Execute := rExecute,
            Abort := rAbort,
            JSONString := ADR(JsonString),
            JSONStringSize := SIZEOF(JsonString),
            JSONVars := ADR(sFileContentsRead_Struct_Json),
            NumberOfVars := SIZEOF(sFileContentsRead_Struct_Json)/SIZEOF(JSONVAR),
            Busy => rBusy,
            Done => rDone,
            Aborted => rAborted,
            Error => rError,
            ErrorPosition => rErrorPosition,
            ParseTime => rComposeTime);

            sFileContentsRead_Struct.fReal := sFileContentsRead_Struct_Json.fReal.Number;
            sFileContentsRead_Struct.nInteger := TO_INT(sFileContentsRead_Struct_Json.nInteger.Integer);
            sFileContentsRead_Struct.sText := sFileContentsRead_Struct_Json.sText.CharString;
            sFileContentsRead_Struct.fLreal := sFileContentsRead_Struct_Json.fLreal.Number;

            TYPE ST_TEST :
            STRUCT

            sText : STRING := 'Hello test';
            nInteger : INT := 10;
            fReal : REAL := 1.234567;
            fLreal : REAL := 1215.2215;
            

            END_STRUCT
            END_TYPE

            TYPE ST_TEST_Json :
            STRUCT
            thisisnew : JSONVAR;
            sText : JSONVAR;
            nInteger : JSONVAR;
            fReal : JSONVAR;
            fLreal :JSONVAR;
            END_STRUCT
            END_TYPE

            This is using only your blocks writing the json string and then parsing back the json string to the same struct. Without the exit change the read struct stayed empty

             
1 2 > >> (Page 1 of 2)

Log in to post a comment.