plctwincatstructured-text

How to add objects into array? (TwinCAT3)


I would like to save my array of objects (arr) into json file from Beckhoff TwinCAT3 using FB_JsonDomParser. This is what I want to get:

{ 'MyArray' : [{a: 1, b: 0.4}, {a: 3, b: 9.1}, {a: 6, b: 0.1}] }

This is my attempt, where I couldn't find anything suitable within push methods.

fbJson : FB_JsonDomParser;
jRoot : SJsonValue;
jArray : SJsonValue;
bSaveJsonFile : BOOL;
arr : ARRAY[0..9] OF MYSTRUCT; // structure contains int and real

jRoot := fbJson.NewDocument();
jArray := fbJson.AddArrayMember(jRoot, 'MyArray', 0);
// not sure how to add objects here into jArray

fbJson.SaveDocumentToFile(sFile := 'C:\tmp\test.json', bExec := bSaveJsonFile);

Solution

  • Not a user of json in TwinCAT, but I played around a bit and created what you are looking for, though I used FB_JsonSaxWriter and FB_JsonReadWriteDataType, let me know if this helps. This could be encapsulated as a function or a method that could be used for generics instead of using specific data type like here, but it should serve as a sufficient example imho.

    Here is the code:

    PROGRAM MAIN
    VAR
        arr : ARRAY [0..3] OF ST_MyDataType := [
            (realVal := 0.0, intVal := 0),
            (realVal := 1.0, intVal := 1),
            (realVal := 2.0, intVal := 2),
            (realVal := 3.0, intVal := 3)];
            
        bWriteToFile    : BOOL;
        bWriteSuccess   : BOOL;
        nArrayIteration : UDINT;
        fbJsonDataType  : FB_JsonReadWriteDataType;
        fbJsonWriter    : FB_JsonSaxWriter;
        fbJson          : FB_JsonDomParser;
        sJsonDoc        : STRING(2000);
        bCreateJsonDoc  : BOOL;
    END_VAR
    
    IF bCreateJsonDoc THEN
        bCreateJsonDoc := FALSE;
        fbJsonWriter.ResetDocument();
        fbJsonWriter.StartObject();
        fbJsonWriter.AddString('My array of structures');
        // Start the array
        fbJsonWriter.StartArray();
        
        // Iterate the array's objects here
        FOR nArrayIteration := 0 TO SIZEOF(arr)/SIZEOF(ST_MyDataType) - 1 BY 1 DO
            // Create an object and the values based on the current iteration of the array
            fbJsonDataType.AddJsonValueFromSymbol(
                fbjsonwriter,
                'ST_MyDataType', 
                SIZEOF(ST_MyDataType), 
                ADR(arr) + nArrayIteration*SIZEOF(ST_MyDataType));
                
            // Object end (all struct members written)
        END_FOR
        
        // End the array and create the json doc as a string to be written
        fbJsonWriter.EndArray();
        fbJsonWriter.EndObject();
        fbJsonWriter.CopyDocument(sJsonDoc, SIZEOF(sJsonDoc));
        fbJson.ParseDocument(sJsonDoc);
    END_IF
    
    bWriteSuccess := fbJson.SaveDocumentToFile(
        bExec := bWriteToFile, 
        sFile := 'C:\JsonTest\Test.json');
    

    Here is the resulting json doc content:

    {"My array of structures":[{"realVal":0.0,"intVal":0},{"realVal":1.0,"intVal":1},{"realVal":2.0,"intVal":2},{"realVal":3.0,"intVal":3}]}
    

    And here is the data type definition:

    TYPE ST_MyDataType :
    STRUCT
        realVal : REAL;
        intVal  : INT;
    END_STRUCT
    END_TYPE
    

    Edit: I did try to use only FB_JsonDomParser but I didn't manage to add Base64Object, it always ended up looking weird. I could add normal objects to array (int, bool, etc...), but when calling FB_JsonDomParser.PushbackBase64Value(jsonSetArrayObject, ADR(stTest), SIZEOF(stTest)); my result would end up looking like this:enter image description here You can clearly see adding booleans works, but adding base 64 as a stand alone member or to be pushed to the array did not work - as mentioned, no experience on this subject, perhaps someone else can give some more valuable input.