Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched.
Close
Hi,
I have a problem.
I get data from http get request in JSON format. When I use http_sys.hTTPClient_0.httpResult.wsContent (WSTRING) everything with chars (UTF-8) is ok. But for the needs JSON Parse I must use http_sys.hTTPClient_0.httpResult.sContent (STRING) data and in this case I have problem with Polish characters.
After parse I create variables to print on HMI(webvisu):
description:= STRING_TO_WSTRING(NewJSONObj.description.AsString);
And the result is that I have no Polish characters. How resolve this problem ?
Last edit: damian177 2022-01-27
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The issue is using string_to function assumes that every char in your string is coded on 8 bits, while UTF8 is on 16 bits. So you are interpreting splitted chars.
I don't know why you "need" to use .sContent to parse, but this could be a way to solve it.
Also you may also just interpret a byte array (string and wsstring are no more than byte arrays) as a wstring using union for instance.
Last edit: dFx 2022-01-27
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
where ASCII is just an enumeration of all ASCII characters (type BYTE).
the code uses the array index, not pointers, to iterate over all the characters.
So, I haven't tried this out, but it might be as simple as changing the ASCII enumeration to WORD type. That would change the array elements to 16 bit, and since WSTRING and STRING are the same for the first 127 characters anyway, anywhere the enumerations are used in the code would be the same.
let me know if that works, I'm not sure if there's a way to allow for both WSTRING and STRING types, but I'll put it on the list of things to think about for future versions
Tim
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry, I just realize that I only implemented the ASCII enumeration in version 1.0.0.12, which I haven't released yet. In the version 1.0.0.11, the JSON strings are referred to as:
{attribute 'displaymode':='hex'}JSONString: POINTER TO ARRAY[1..GPL_JSON.MAX_JSON_STRING] OF BYTE; //pointer to JSON string
which might mean you just have to change the BYTE to a WORD
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thinking about it a bit more, there's probably some changes that would need to be made to the JSONVAR function block as well. Line 110 of JSON_TO_STRUCT is where the value from the JSON string is written to the local variable. It uses the JSONVAR.AsString method. It takes a STRING type, which in turn uses the STRING_TO_JSONVALUE function to guess at what type the value is.
I think all of those points would also have to be changed.
Last edit: tvm 2022-01-27
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
For tests I will change only BYTE to WORD like you said, but in my STRUCT's (NewJSONObj) I won't use JSONVAR only WSTRING. And calling ParseJSON would be:
I do not think this will work, because JSON_TO_STRUCT is expecting the JSONVars input to consist of only variables of JSONVAR type. It doesn't matter if they are a STRUCT or an ARRAY on the outside, but within the function block they are all addressed as an ARRAY OF JSONVAR.
The more I look at it, I think it would require a substantial rewrite. Basically everything would have to be changed to WSTRING internally.
Which might be something to look at in the future, but it's not a quick fix.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I rewrited all Your library changing all STRING datatypes to WSTRING, and change functiona like LEN, DELETE etc to WLEN, WDELETE etc ... and partially works.
It looks like that finde the tag's but it have a problem witch data lenght. For example it is my test data in WSTRING JSON:
MAX_NAME_SIZE: UINT:= 20; //max string length of JSON name MAX_VALUE_SIZE: UINT:= 20; //max value size in bytes (all values are this size in memory)
These were basically only to limit memory usage. For example, MAX_VALUE_SIZE is the number of bytes that each JSONVAR uses for internal variable storage, regardless of type. So if all your JSON variables are booleans or numbers, it could probably be 4 bytes. In your case, with a lot of strings, it needs to be longer.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Did you increase the values in the library, or in your project? Because I've noticed in the past that if I change a value in a parameter list in the library, it doesn't change in the project unless I do it there as well
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I do not can edit library. In my project create structs, fb, fun with with a "_ 16" note to the original name.
My global variables : GPL_JSON_16 and ther I chcnege value.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
According with described above logic, I created JSONVAR_16 and change like this:
{attribute 'pack_mode' := '4'}{attribute 'reflection'}{attribute 'symbol' := 'none'}FUNCTION_BLOCK JSONVAR_16VAR_INPUT Names: ARRAY[1..GPL_JSON_16.MAX_LEVELS] OF JSONVARNAME_16; //variable path as an array. [1] is variable name, [2..x] are higher level structures END_VARVAR {attribute 'instance-path'}{attribute 'noinit'} {attribute 'hide'}_VarNameFull: WSTRING(GPL_JSON_16.MAX_VAR_NAME); //JSON name uses the variable name {attribute 'hide'}_ValueType: JSONVALUETYPE_16:= JSONVALUETYPE_16.json_null; //type of variable contained in the value field, also implicity defines size of local var {attribute 'hide'}_InternalValue: ARRAY[1..GPL_JSON_16.MAX_VALUE_SIZE+1] OF WORD; //value stored internally as an array of bytes {attribute 'hide'}_Size: UINT; //size of internal value in bytes, automatically determined when any of the type properties are set {attribute 'hide'}_ApplicationLevel: INT; //array position which points to the applicationEND_VARVAR_OUTPUT {attribute 'symbol' := 'read'}HMIVarAsWString: WSTRING(GPL_JSON_16.MAX_VALUE_SIZE); //this output is updated every time AsString property is set, for use with external HMI through sumbol configurationEND_VARVAR_STAT {attribute 'hide'}PrevApplicationLevel: REFERENCE TO INT; //highest variable name in previous variable {attribute 'hide'}PrevNameArray: REFERENCE TO ARRAY[1..GPL_JSON_16.MAX_LEVELS] OF JSONVARNAME_16;//path of the previous variableEND_VAR
this copies bytes from the JSON string into a temporary buffer containing the name and value. The NAMEVALUE buffer should be fine, but the udiCount input to SysMemCpy is in bytes, and should be doubled, I think
Hi,
I have a problem.
I get data from http get request in JSON format. When I use http_sys.hTTPClient_0.httpResult.wsContent (WSTRING) everything with chars (UTF-8) is ok. But for the needs JSON Parse I must use http_sys.hTTPClient_0.httpResult.sContent (STRING) data and in this case I have problem with Polish characters.
After parse I create variables to print on HMI(webvisu):
description:= STRING_TO_WSTRING(NewJSONObj.description.AsString);
And the result is that I have no Polish characters. How resolve this problem ?
Last edit: damian177 2022-01-27
The issue is using string_to function assumes that every char in your string is coded on 8 bits, while UTF8 is on 16 bits. So you are interpreting splitted chars.
I don't know why you "need" to use .sContent to parse, but this could be a way to solve it.
Also you may also just interpret a byte array (string and wsstring are no more than byte arrays) as a wstring using union for instance.
Last edit: dFx 2022-01-27
When I use .wsContent teh JSON Parse doesn't work.
In JSON struct we not have a WSTRING data , only STRING. Please find in attachement.
I use PRO_JSON library:
https://forge.codesys.com/lib/pro-json/home/Home/
Last edit: damian177 2022-01-27
Someone tried Parse JSON from WSTRING by PRO_JSON library ?
Hi
I created the PRO_JSON library. It's designed to use STRING types, but the functions refer to the strings like this:
where ASCII is just an enumeration of all ASCII characters (type BYTE).
the code uses the array index, not pointers, to iterate over all the characters.
So, I haven't tried this out, but it might be as simple as changing the ASCII enumeration to WORD type. That would change the array elements to 16 bit, and since WSTRING and STRING are the same for the first 127 characters anyway, anywhere the enumerations are used in the code would be the same.
let me know if that works, I'm not sure if there's a way to allow for both WSTRING and STRING types, but I'll put it on the list of things to think about for future versions
Tim
In library is:
{attribute 'displaymode':='hex'}JSONString: POINTER TO ARRAY[1..GPL_JSON.MAX_JSON_STRING] OF BYTE; //pointer to JSON string
I should change to:
{attribute 'displaymode':='hex'}JSONString: POINTER TO ARRAY[1..GPL_JSON.MAX_JSON_STRING] OF WORD; //pointer to JSON string
Ho change it in library function ? It is no edited ...
Yes.
You should be able to open the .library file and make the changes and then save it to your own library repository
Sorry, I just realize that I only implemented the ASCII enumeration in version 1.0.0.12, which I haven't released yet. In the version 1.0.0.11, the JSON strings are referred to as:
{attribute 'displaymode':='hex'}JSONString: POINTER TO ARRAY[1..GPL_JSON.MAX_JSON_STRING] OF BYTE; //pointer to JSON string
which might mean you just have to change the BYTE to a WORD
Thinking about it a bit more, there's probably some changes that would need to be made to the JSONVAR function block as well. Line 110 of JSON_TO_STRUCT is where the value from the JSON string is written to the local variable. It uses the JSONVAR.AsString method. It takes a STRING type, which in turn uses the STRING_TO_JSONVALUE function to guess at what type the value is.
I think all of those points would also have to be changed.
Last edit: tvm 2022-01-27
For tests I will change only BYTE to WORD like you said, but in my STRUCT's (NewJSONObj) I won't use JSONVAR only WSTRING. And calling ParseJSON would be:
What do you think ? it enought ?
Last edit: damian177 2022-01-27
I do not think this will work, because JSON_TO_STRUCT is expecting the JSONVars input to consist of only variables of JSONVAR type. It doesn't matter if they are a STRUCT or an ARRAY on the outside, but within the function block they are all addressed as an ARRAY OF JSONVAR.
The more I look at it, I think it would require a substantial rewrite. Basically everything would have to be changed to WSTRING internally.
Which might be something to look at in the future, but it's not a quick fix.
I rewrited all Your library changing all STRING datatypes to WSTRING, and change functiona like LEN, DELETE etc to WLEN, WDELETE etc ... and partially works.
It looks like that finde the tag's but it have a problem witch data lenght. For example it is my test data in WSTRING JSON:
{"id":25,"Tag":"RRWWQQAAQQ","description":"ΕΕΔΓ³ΕuΔ QΓ³ΕΕ","comment":"test1"}
After parsing I have good data but not all length - please find in attachement ...
Any idea what should i change ?
Feels like end of string detection isn't right. Maybe the lib was testing a byte, where you should test a word to NULL when using WSTRING.
line 41 of JSON_TO_STRUCT limits the loop to either finding a null character, or the total string size. Did you change the ASCII enumeration to WORD?
You talking about this function ?:
When Iuse HMIVarAsWString variable is better, but still not full values in variables
Last edit: damian177 2022-01-28
Try increasing these values in GPL_JSON
These were basically only to limit memory usage. For example, MAX_VALUE_SIZE is the number of bytes that each JSONVAR uses for internal variable storage, regardless of type. So if all your JSON variables are booleans or numbers, it could probably be 4 bytes. In your case, with a lot of strings, it needs to be longer.
I increased this values but without effect.
Actually it is a number of WORD :
OR
{attribute 'monitoring':='call'}PROPERTY AsWString : WSTRING(GPL_JSON_16.MAX_VALUE_SIZE)
Did you increase the values in the library, or in your project? Because I've noticed in the past that if I change a value in a parameter list in the library, it doesn't change in the project unless I do it there as well
I do not can edit library. In my project create structs, fb, fun with with a "_ 16" note to the original name.
My global variables : GPL_JSON_16 and ther I chcnege value.
OK, what about in JSONVAR
should that also be changed to a WORD, or is it big enough anyway?
According with described above logic, I created JSONVAR_16 and change like this:
Related
Talk.ru: 1
OK, I have another idea.
Take a look in JSON_TO_STRUCT.Value, line 65-70
this copies bytes from the JSON string into a temporary buffer containing the name and value. The NAMEVALUE buffer should be fine, but the udiCount input to SysMemCpy is in bytes, and should be doubled, I think
it's better with this change. In HMIVarAsWStrin I have all data from variable, but in AsWString is still to small.
Please find in attachement.
Last edit: damian177 2022-01-28
What about property JSONVAR.CharString?
In your new function WSTRING_TO_JSONVALUE, you still have this line. Did CharString get changed to WSTRING type?