Closed mailow-vsl closed 11 months ago
@mailow-vsl Notice the whitespace between the two key-value pairs. To accomodate this, you need to either:
#define JSON_SKIP_WHITESPACE
before #include "json.h"
, or-DJSON_SKIP_WHITESPACE
Note: This would incur a small overhead to skip the whitespaces.
After parsing, get the integer value by (int) element.value.as_number.value.as_long
. See example below for your usecase:
const char *json = "{\"level\":15, \"temperature\":125}";
result(json_element) element_result = json_parse(json);
if (result_is_err(json_element)(&element_result)) {
typed(json_error) error = result_unwrap_err(json_element)(&element_result);
fprintf(stderr, "Error parsing JSON: %s\n", json_error_to_string(error));
return -1;
}
typed(json_element) element = result_unwrap(json_element)(&element_result);
if (element.type == JSON_ELEMENT_TYPE_OBJECT) {
result(json_element) r_temp =
json_object_find(element.value.as_object, "temperature");
if (result_is_ok(json_element)(&r_temp)) {
typed(json_element) temp = result_unwrap(json_element)(&r_temp);
printf("Temperature is %d\n", (int)temp.value.as_number.value.as_long);
}
}
json_free(&element);
Hope this solves your issue
Oh, excelent, that worked. Thank you, sending beers ;)
Please may I have one more question @forkachild? How I can fetch nested elements? Like this
const char * UART_RX_PC_Buffer = "{\"confMode\":1,\"morning\":{\"over\":1,\"start\":\"10:30\",\"end\":\"16:00\"},\"crc\":123456}";
int hour, minute;
int confMode, crc;
int LANOverEco, LANTimeStartEco, LANTimeEndEco;
int main()
{
result(json_element) element_result = json_parse(UART_RX_PC_Buffer);
// Guard if
if(result_is_err(json_element)(&element_result)) return -1;
// Extract the data
typed(json_element) element = result_unwrap(json_element)(&element_result);
// Fetch the "confMode" key value .. and others
if (element.type == JSON_ELEMENT_TYPE_OBJECT) {
result(json_element) r_confMode = json_object_find(element.value.as_object, "confMode");
if (result_is_ok(json_element)(&r_confMode)) {
typed(json_element) t_confMode = result_unwrap(json_element)(&r_confMode);
confMode = (int)t_confMode.value.as_number.value.as_long;
}
}
switch(confMode) {
case 1: //ECO
if (element.type == JSON_ELEMENT_TYPE_OBJECT) {
result(json_element) r_start = json_object_find(element.value.as_object, "start");
if (result_is_ok(json_element)(&r_start)) {
typed(json_element) t_start = result_unwrap(json_element)(&r_start);
if (sscanf(t_start.value.as_string, "%d:%d", &hour, &minute) == 2) LANTimeStartEco = hour * 60 + minute;
}
}
if (element.type == JSON_ELEMENT_TYPE_OBJECT) {
result(json_element) r_end = json_object_find(element.value.as_object, "end");
if (result_is_ok(json_element)(&r_end)) {
typed(json_element) t_end = result_unwrap(json_element)(&r_end);
if (sscanf(t_end.value.as_string, "%d:%d", &hour, &minute) == 2) LANTimeEndEco = hour * 60 + minute;
}
}
if (element.type == JSON_ELEMENT_TYPE_OBJECT) {
result(json_element) r_over = json_object_find(element.value.as_object, "over");
if (result_is_ok(json_element)(&r_over)) {
typed(json_element) t_over = result_unwrap(json_element)(&r_over);
LANOverEco = (int)t_over.value.as_number.value.as_long;
}
}
if (element.type == JSON_ELEMENT_TYPE_OBJECT) {
result(json_element) r_crc = json_object_find(element.value.as_object, "crc");
if (result_is_ok(json_element)(&r_crc)) {
typed(json_element) t_crc = result_unwrap(json_element)(&r_crc);
crc = (int)t_crc.value.as_number.value.as_long;
}
}
break;
case 2: //AUTO
// code block
break;
}
json_print(&element, 1);
printf("\n\nconfMode: %d, start: %d, end: %d, over: %d, crc: %d\n", confMode, LANTimeStartEco, LANTimeEndEco,LANOverEco, crc);
return 0;
}
So here I tried to find the key "over" (some flag) and "start" and "end" keys and count minutes after midnight. Am I doing it wrong?
I can see that structure is parsed correctly.
{
"confMode": 1,
"morning": {
"start": "10:30",
"end": "16:00",
"over": 1
},
"crc": 123456
}
But my values in my output printf are not.
confMode: 1, start: 0, end: 0, over: 0, crc: 123456
I suppose I miss something, because in my next structure I need to separate individual times during the day which are nested in day phases :)
{
"confMode": 2,
"morning": {
"over": 1,
"start": "7:30",
"end": "9:00"
},
"afternoon": {
"over": 1,
"start": "15:00",
"end": "19:00"
},
"duringday": {
"over": 0,
"start": "9:00",
"end": "15:00"
},
"crc": 12345
}
@mailow-vsl Yes, you need to parse the "morning"
, "afternoon"
& "duringday"
level elements first and then parse values from inside those objects.
What I have noticed is, parsing each level like this requires writing a lot of boilerplate. I was thinking about a MACRO like
#define result_guard_else_return(type, resval, varname, retval) \
result(type) r_##varname = resval; \
if (result_is_err(type)(&r_##varname)) \
return retval; \
typed(type) varname = result_unwrap(type)(&r_##varname);
Note: This is just a rough idea
This can result in simplified statements like
result_guard_else_return(json_element, json_parse(UART_RX_PC_Buffer), root, -1);
result_guard_else_return(json_element, json_object_find(root.value.as_object, "confMode"), t_confMode, -1);
confMode = (int) t_confMode.value.as_number.value.as_long;
What is your opinion? I'm open to ideas.
Ok, seems that if I parse it like you said, it works. it's a bit of extra work, but I'm fine with that so far ;)
Thx for your help and advice and for your amazing lib :P
Hi @forkachild , I am trying to use your library in a project with STM32 microprocessor. It works like a charm, but only for string values. How I can fetch int value of the elements? I need to store the value in other variables to work with them and store them to EEPROM memory.
Eg how to fetch int values when parsing {"level":15, "temperature":125} to store them like int?