JSON String in Struktur packen

Chris_O

Level-1
Beiträge
9
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich hätte da mal eine Frage an euch. Ich verwende aktuell TwinCat3 und bekomme via HTTP POST eine Antwort von einem Server im JSON-Format.
über die Funktion "SetSymbolFromJson" kann ich nun meine Antwort in eine Struktur packen. Das funktioniert auch soweit ganz gut.
Die Probleme:
1. bei der Funktion "SetSymbolFromJson" muss ich den Namen meiner Struktur als String mit angeben. Vertippe ich mich hier, wird einfach nichts in die Struktur geschrieben und ich bekomme auch keine Rückmeldung, dass irgend etwas schief gelaufen ist.
2. Habe ich mich in der Struktur generell geirrt (passt also die Antwort nicht zur Struktur), wird auch einfach nichts in die Struktur geschrieben, ohne dass ich eine Rückmeldung dazu bekomme

Kennt jemand eine Möglichkeit, wie ich auswerten könnte, ob mein Versuch erfolgreich war, die Daten in die Struktur zu packen?

Die Krux dabei ist, dass ich einen Baustein geschrieben habe, der von außen universell verwendet werden kann. D.h. ich weiß aktuell nicht, welche Struktur ich im Endeffekt wirklich habe... hatte zuerst den Gedanken bei jeder Anforderung zum Server die Struktur erst mal mit einem Initialwert zu füllen... dann würde ich ja sehen, wenn sich etwas ändert... Aber wie kann ich das innerhalb meines Bausteins machen, wenn ich als Input (wo später die Struktur drauf gelegt wird) eine "PVOID" Variable habe?
Jemand ne Idee? (Ich hoffe mein Wirres Gerede gibt einigermaßen Sinn :D )

Codesnipped:
Deklaration meines FB's:
Code:
VAR_INPUT
    bSend                     : BOOL; //Start send at rising edge
    bResetError            : BOOL;    //Reset Error
  

    sStructName            : STRING;
    udiSizeOfData         : UDINT; // size of struct for data to be send
    pData                      : PVOID; // Adress of struct for data to be send
    sContentType          : STRING:='application/json'; //optional (init with 'application/json')
  
    sStructNameResult       : STRING; //optional (e.g. 'ST_MesCheckSerialsResponse' / init depending on eCurrentMesMode)
    udiSIzeOfDataResult    : UDINT; // size of struct for data to be received
    pResult                         : PVOID; // Adress of struct for data to be received
  
          
    sHostname            : STRING;
    sIdentifier              : STRING;
    uiPort                     : UINT;
END_VAR

Programmteil:

("sResultValue" enthält den JSON-String)

Code:
IF pResult<> 0 THEN
     fbJsonDataType.SetSymbolFromJson(sResultValue, sStructNameResult, udiSIzeOfDataResult, pResult );
                                    
ELSE
     bError:=TRUE;
     sErrorText:='No valid inputs';
END_IF
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi, danke dir für den Hinweis...
da bin ich auch schon drauf gestoßen... leider scheint das aber nicht zu stimmen. Ich hab mal versucht eine Struktur zu verwenden, wo z.B. noch ein Eintrag mehr drin ist. Ebenso habe ich mal versucht den String (hier im Beispiel "ST_Values") falsch zu schreiben.
Die Funktion liefert trotzdem ein TRUE zurück und es wird mir nichts in meine Struktur geschrieben...

Edit:
Stimmt nicht ganz, was ich geschrieben habe. Wenn zusätzliche Einträge in der Struktur sind, stört das die Funktion nicht und Sie schreibt trotzdem was rein (ggf. aber an die falsche Stelle). Wenn die Struktur so gar nicht passt, bekomme ich auch die Rückmeldung "FALSE".
Wenn aber die Struktur generell passt, jedoch der String falsch geschrieben ist, sagt die Funktion "alles OK", schreibt aber nichts rein.

Wenn niemand eine Idee hat, werd ich wohl erst mal damit leben müssen...
 
Zuletzt bearbeitet:
Ich überlege gerade, ob die JSON-Response vom Server unbedingt in eine komplette Struct muss, oder ob man das etwas vereinfachen könnte. Kannst du mal so eine Response als Beispiel posten und evtl. auch dazuschreiben, was du mit der Antwort anstellen willst?
 
Hmh...
ich hab je nach Anfrage verschiedene Antworten vom Server.
Z.B. die Standard Response, wenn ich Abfrage ob die Seriennummer schon vorhanden ist:
Code:
TYPE ST_MesStandardResponse :
STRUCT
    RESULT_CODE: INT;
    RESULT_TEXT: STRING;
END_STRUCT
END_TYPE

Hierbei Erhalte ich z.B. RESULT_CODE "0" und RESULT_TEXT "OK"
Oder eben einen Fehlercode mit entsprechendem Fehlertext.

Oder ich Frage beim Server den "MaterialSetup" ab. Da würde ich dann sowas erhalten:
Code:
TYPE ST_MesCheckMaterialResponse :
STRUCT
    RESULT_CODE    : INT;
    RESULT_TEXT    : STRING;
    SETUP        : ARRAY[0..2] OF ST_MesCheckMaterialResponseEntry;
END_STRUCT
END_TYPE

Code:
TYPE ST_MesCheckMaterialResponseEntry :
STRUCT
    DESCRIPTION: STRING;
    VALID: INT;
    MATERIAL_BIN: STRING;
    PARTNUMBER: STRING;
    SETUP_POSITION: STRING;
    BATCH_1: STRING;
    QTY_TOTAL: REAL;
    QTY_CURR: REAL;
END_STRUCT
END_TYPE

Entsprechend diesen Antworten kann dann die Maschine sagen, ob die Seriennummer noch angelegt werden muss, ob das Material in Ordnung ist etc,...

Die Response würde "Nakt" z.B. so aussehen:
{"RESULT_CODE":-110,"RESULT_TEXT":"Serialnumber not found"}'

Oder auch ggf. so:
{"RESULT_CODE":5,"SERIAL_NUMBERS":[{"SERIAL_NUMBER":"Test_Sn6","RESULT_CODE":-110,"RESULT_TEXT":"Serialnumber not found"},{"SERIAL_NUMBER":"Test_Sn7","RESULT_CODE":-110,"RESULT_TEXT":"Serialnumber not found"}],"RESULT_TEXT":"Error @5 Occurs. Error Description not found in DB!"}

Hier würde dann die Struktur so aussehen:
Code:
TYPE ST_MesCheckSerialsResponse :
STRUCT
    RESULT_CODE        : INT;
    SERIAL_NUMBERS     : ARRAY[0..1] OF ST_MesCheckSerialsResponseEntry;
    RESULT_TEXT        : STRING;   
END_STRUCT
END_TYPE

Code:
TYPE ST_MesCheckSerialsResponseEntry :
STRUCT
    SERIAL_NUMBER    : STRING;
    RESULT_CODE        : DINT;
    RESULT_TEXT     : STRING;
    
END_STRUCT
END_TYPE
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Im Endeffekt muss ich nur eine Lösung finden, um zu sagen ob das Schreiben in die Struktur funktioniert hat oder nicht (Daten gültig oder nicht) Die separate Auswertung der Daten ist erst mal zweitranging.

Ich müsste irgendwie in meinem FB die Struktur, die von außen auf den Input gelegt wird mit einem Standard-Wert initialisieren. Dann könnte ich ja relativ leicht auswerten, ob sich was getan hat... aber da finde ich gerade keine Lösung, da ich im Baustein ja nicht die Struktur, sondern nur deren Adresse habe. Ich weiß ja in dem Moment auch nicht wie die Struktur aussieht, die von außen drauf gegeben wird...
 
Ich müsste irgendwie in meinem FB die Struktur, die von außen auf den Input gelegt wird mit einem Standard-Wert initialisieren. Dann könnte ich ja relativ leicht auswerten, ob sich was getan hat... aber da finde ich gerade keine Lösung, da ich im Baustein ja nicht die Struktur, sondern nur deren Adresse habe. Ich weiß ja in dem Moment auch nicht wie die Struktur aussieht, die von außen drauf gegeben wird...
Naja, da du ja Adresse und Länge der Struktur weißt, könnte man ja mit MEMSET alle Bytes der Struktur auf "0" setzen und temporär wegkopieren mit MEMCPY.
Dann SetSymbolFromJson ausführen und das Ergebnis mit dem "wegkopiertem" mit Hilfe von MEMCMP vergleichen.

Ist aber keine schöne Lösung. Man muss dann ausschließen können, dass die Struktur mit "0" initialisiert auf jeden Fall kein gültiges Ergebnis sein darf.
 
Naja, da du ja Adresse und Länge der Struktur weißt, könnte man ja mit MEMSET alle Bytes der Struktur auf "0" setzen und temporär wegkopieren mit MEMCPY.
Dann SetSymbolFromJson ausführen und das Ergebnis mit dem "wegkopiertem" mit Hilfe von MEMCMP vergleichen.

Ist aber keine schöne Lösung. Man muss dann ausschließen können, dass die Struktur mit "0" initialisiert auf jeden Fall kein gültiges Ergebnis sein darf.
Ja, das war mein aller erster Ansatz mit MEMSET = 0 🙃
Aber leider ist der Haken dass Error-Code = 0 kommen würde, wenn alles OK ist... und der Error-Text ist etwas unzuverlässig, da der in der DB nicht immer gepflegt ist... ich hätte dann nur auf den Error-Code geschaut...

Aber wie genau meinst du das mit dem temporären wegkopieren? Wohin? Ich muss ja auf irgend eine Struktur / Speicherbereich kopieren, um anschließend das Ergebnis von SetSymbolFromJson zu vergleichen.... Ich kann mir ja nicht einfach eine Dynamische Struktur deklarieren :)... oder?!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Einfach eine Byte Array Variable mit der Max. möglichen Strukturgröße deklarieren. Diese ist ja bekannt.
Mir fällt gerade auf, dass man ja gar nicht wegkopieren muss, da in dem Array ja alles "0" ist und darauf ja nie geschrieben wird.
 
Einfach eine Byte Array Variable mit der Max. möglichen Strukturgröße deklarieren. Diese ist ja bekannt.
Mir fällt gerade auf, dass man ja gar nicht wegkopieren muss, da in dem Array ja alles "0" ist und darauf ja nie geschrieben wird.
Hmh... also die Struktur mit einem komplett leeren Byte-Array verglichen habe ich jetzt noch nicht ausprobiert.... bisher hatte ich auch noch nie den Fall, dass ich eine komplett leere Antwort bzw. mit lauter 0 bekommen habe... könnte vielleicht gehen....

Werd mich nochmal melden :)
 
Einfach eine Byte Array Variable mit der Max. möglichen Strukturgröße deklarieren. Diese ist ja bekannt.
Mir fällt gerade auf, dass man ja gar nicht wegkopieren muss, da in dem Array ja alles "0" ist und darauf ja nie geschrieben wird.

Hmh... also die Struktur mit einem komplett leeren Byte-Array verglichen habe ich jetzt noch nicht ausprobiert.... bisher hatte ich auch noch nie den Fall, dass ich eine komplett leere Antwort bzw. mit lauter 0 bekommen habe... könnte vielleicht gehen....

Werd mich nochmal melden :)

Das scheint doch tatsächlich so zu funktionieren :)
Ist wie gesagt zwar nicht so wunderschön... aber besser als vorher ist es auf jeden Fall!

Danke nochmal für die Hilfe.
Sollte noch jemandem einen bessere Lösung einfallen... nur her damit :)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Im Endeffekt muss ich nur eine Lösung finden, um zu sagen ob das Schreiben in die Struktur funktioniert hat oder nicht (Daten gültig oder nicht) Die separate Auswertung der Daten ist erst mal zweitranging.

Dann würde es ja reichen, wenn du gar nicht in die Struct kopierst, sondern die Zeichenkette nur inspizierst.

Code:
jsonDoc := fbJson.ParseDocument(sMessage);
bHasMember := fbJson.HasMember(jsonDoc, 'RESULT_CODE');
IF (bHasMember) THEN
  bHasMember := FALSE;
  jsonProp := fbJson.FindMember(jsonDoc, 'RESULT_CODE');
  nResultCode := fbJson.GetString(jsonProp);
END_IF

IF nResultCode >= 0 THEN
  // hat funktioniert
ELSE
  // hat nicht funktioniert
END_IF

https://infosys.beckhoff.com/index....1031/tcplclib_tc3_jsonxml/3664756363.html&id=

Wäre das eine Möglichkeit?
 
Zurück
Oben