Предложение синтаксического анализа cJSON
Я пытаюсь проанализировать приведенную ниже строку JSON в моем коде микроконтроллера с помощью CJSON.
{
"A":
{
"A1":
[
{"S":0,"V":-5},
{"S":60,"V":5}
],
"A2":
[
{"S":0,"V":-5},
{"S":60,"V":5}
]
},
"B":
{
"B1":
[
{"S":0,"V":-5},
{"S":60,"V":5}
],
"B2":
[
{"S":0,"V":-5},
{"S":60,"V":5}
]
},
"C":60
}
Я попытался сделать это до сих пор, чтобы отфильтровать строку A. Затем я могу снова запустить анализ для фильтрации A1 из A. Код не сработал. Его печать "error_ptr".
int cJSON_Test()
{
char text[1024];
char JSON_STRING[] =
"{\n"
"\"A\":{\"A1\":[{\"S\":0,\"V\":-5},{\"S\":60,\"V\":5}],\"A2\":[{\"S\":0,\"V\":-5},{\"S\":60,\"V\":5}]},\n"
"\"B\":{\"B1\":[{\"S\":0,\"V\":-5},{\"S\":60,\"V\":5}],\"B2\":[{\"S\":0,\"V\":-5},{\"S\":60,\"V\":5}]},\n"
"\"C\":60\n"
"}";
const cJSON *A_Data = NULL;
const cJSON *B_Data = NULL;
const cJSON *C_Data = NULL;
const cJSON *A1_Data = NULL;
const cJSON *A2_Data = NULL;
int status = 0;
cJSON *root = cJSON_Parse(JSON_STRING);
if (root == NULL)
{
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
sprintf(text,"Error before: %s\r\n", error_ptr);
SendDataToUart(&huart1, (uint8_t*)text, strlen(text));
}
status = 0;
goto end;
}
A_Data = cJSON_GetObjectItemCaseSensitive(root, "A");
if (cJSON_IsString(A_Data) && (A_Data->valuestring != NULL))
{
sprintf(text,"A String: %s\r\n", A_Data->valuestring);
SendDataToUart(&huart1, (uint8_t*)text, strlen(text));
}
end:
cJSON_Delete(root);
return status;
}
Мне нужно разобрать всю строку и ее значение отдельно, а затем распечатать. Может кто-нибудь, пожалуйста, совет?
С уважением.
1 ответ
Вы можете отлаживать проблемы с вашим распределителем, создавая оболочки, которые затем устанавливаете с помощью cJSON_InitHooks.
Я написал пример того, как ваш ввод может быть проанализирован, а также некоторые средства отладки отладки, которые должны помочь вам найти проблему. Просто замените все printf
с вашей функцией отправлять строки через UART.
#include <cjson/cJSON.h>
#include <stdio.h>
#include <stdlib.h>
size_t total_allocated = 0;
void *debugging_malloc(size_t size) {
void *pointer = malloc(size);
if (pointer == NULL) {
printf("Failed to allocate %zu bytes\n", size);
} else {
total_allocated += size;
printf("Allocated %zu bytes: %p\n", size, pointer);
}
return pointer;
}
void debugging_free(void *pointer) {
free(pointer);
printf("Freed %p\n", pointer);
}
cJSON_Hooks debugging_allocators = {debugging_malloc, debugging_free};
int print_s_v_array(const cJSON *array, const char *name) {
const cJSON *element = NULL;
size_t index = 0;
printf("\t%s: [", name);
cJSON_ArrayForEach(element, array) {
cJSON *S = NULL;
cJSON *V = NULL;
if (!cJSON_IsObject(element)) {
return 0;
}
S = cJSON_GetObjectItemCaseSensitive(element, "S");
if (!cJSON_IsNumber(S)) {
return 0;
}
V = cJSON_GetObjectItemCaseSensitive(element, "V");
if (!cJSON_IsNumber(V)) {
return 0;
}
printf("\t%zu: S is %f and V is %f\n", index, S->valuedouble, V->valuedouble);
index++;
}
printf("\t]\n");
return 1;
}
cJSON_bool print_sub_object(const cJSON *object, const char *name) {
cJSON *element = NULL;
printf("%s: {\n", name);
cJSON_ArrayForEach(element, object) {
if (!cJSON_IsArray(element) || (element->string == NULL)) {
return 0;
}
print_s_v_array(element, element->string);
}
printf("}\n");
return 1;
}
int main() {
char JSON_STRING[] =
"{\n"
"\"A\":{\"A1\":[{\"S\":0,\"V\":-5},{\"S\":60,\"V\":5}],\"A2\":[{\"S\":0,\"V\":-5},{\"S\":60,\"V\":5}]},\n"
"\"B\":{\"B1\":[{\"S\":0,\"V\":-5},{\"S\":60,\"V\":5}],\"B2\":[{\"S\":0,\"V\":-5},{\"S\":60,\"V\":5}]},\n"
"\"C\":60\n"
"}";
const cJSON *A = NULL;
const cJSON *B = NULL;
const cJSON *C = NULL;
const cJSON *A1 = NULL;
const cJSON *A2 = NULL;
const cJSON *B1 = NULL;
const cJSON *B2 = NULL;
const cJSON *element = NULL;
size_t index = 0;
int status = EXIT_SUCCESS;
cJSON_InitHooks(&debugging_allocators);
cJSON *root = cJSON_Parse(JSON_STRING);
if (root == NULL) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
printf("Error before: %s\r\n", error_ptr);
}
goto fail;
}
A = cJSON_GetObjectItemCaseSensitive(root, "A");
if (!cJSON_IsObject(A)) {
goto fail;
}
print_sub_object(A, "A");
/* you could of course just get A1 and A2 via cJSON_GetObjectItemCaseSensitive manually
* instead of making such a function, not sure what you actually want to do with your data */
B = cJSON_GetObjectItemCaseSensitive(root, "B");
if (!cJSON_IsObject(B)) {
goto fail;
}
print_sub_object(B, "B");
C = cJSON_GetObjectItemCaseSensitive(root, "C");
if (!cJSON_IsNumber(C)) {
goto fail;
}
printf("C: %f\n", C->valuedouble);
goto end;
fail:
status = EXIT_FAILURE;
end:
cJSON_Delete(root);
printf("Allocated in total: %zu bytes\n", total_allocated);
return status;
}
При запуске этого на моем компьютере x86_64 он выводит следующее:
Allocated 64 bytes: 0xf14a51915d0
Allocated 64 bytes: 0xf14a5192630
Allocated 3 bytes: 0xf14a5192680
Allocated 64 bytes: 0xf14a51926a0
Allocated 4 bytes: 0xf14a51926f0
Allocated 64 bytes: 0xf14a5192710
Allocated 64 bytes: 0xf14a5192760
Allocated 3 bytes: 0xf14a51927b0
Allocated 64 bytes: 0xf14a51927d0
Allocated 3 bytes: 0xf14a5192820
Allocated 64 bytes: 0xf14a5192840
Allocated 64 bytes: 0xf14a5192890
Allocated 3 bytes: 0xf14a51928e0
Allocated 64 bytes: 0xf14a5192900
Allocated 3 bytes: 0xf14a5192950
Allocated 64 bytes: 0xf14a5192970
Allocated 4 bytes: 0xf14a51929c0
Allocated 64 bytes: 0xf14a51929e0
Allocated 64 bytes: 0xf14a5192a30
Allocated 3 bytes: 0xf14a5192a80
Allocated 64 bytes: 0xf14a5192aa0
Allocated 3 bytes: 0xf14a5192af0
Allocated 64 bytes: 0xf14a5192b10
Allocated 64 bytes: 0xf14a5192b60
Allocated 3 bytes: 0xf14a5192bb0
Allocated 64 bytes: 0xf14a5192bd0
Allocated 3 bytes: 0xf14a5192c20
Allocated 64 bytes: 0xf14a5192c40
Allocated 3 bytes: 0xf14a5192c90
Allocated 64 bytes: 0xf14a5192cb0
Allocated 4 bytes: 0xf14a5192d00
Allocated 64 bytes: 0xf14a5192d20
Allocated 64 bytes: 0xf14a5192d70
Allocated 3 bytes: 0xf14a5192dc0
Allocated 64 bytes: 0xf14a5192de0
Allocated 3 bytes: 0xf14a5192e30
Allocated 64 bytes: 0xf14a5192e50
Allocated 64 bytes: 0xf14a5192ea0
Allocated 3 bytes: 0xf14a5192ef0
Allocated 64 bytes: 0xf14a5192f10
Allocated 3 bytes: 0xf14a5192f60
Allocated 64 bytes: 0xf14a5192f80
Allocated 4 bytes: 0xf14a5192fd0
Allocated 64 bytes: 0xf14a5192ff0
Allocated 64 bytes: 0xf14a5193040
Allocated 3 bytes: 0xf14a5193090
Allocated 64 bytes: 0xf14a51930b0
Allocated 3 bytes: 0xf14a5193100
Allocated 64 bytes: 0xf14a5193120
Allocated 64 bytes: 0xf14a5193170
Allocated 3 bytes: 0xf14a51931c0
Allocated 64 bytes: 0xf14a51931e0
Allocated 3 bytes: 0xf14a5193230
Allocated 64 bytes: 0xf14a5193250
Allocated 3 bytes: 0xf14a51932a0
A: {
A1: [ 0: S is 0.000000 and V is -5.000000
1: S is 60.000000 and V is 5.000000
]
A2: [ 0: S is 0.000000 and V is -5.000000
1: S is 60.000000 and V is 5.000000
]
}
B: {
B1: [ 0: S is 0.000000 and V is -5.000000
1: S is 60.000000 and V is 5.000000
]
B2: [ 0: S is 0.000000 and V is -5.000000
1: S is 60.000000 and V is 5.000000
]
}
C: 60.000000
Freed 0xf14a51927b0
Freed 0xf14a5192760
Freed 0xf14a5192820
Freed 0xf14a51927d0
Freed 0xf14a5192710
Freed 0xf14a51928e0
Freed 0xf14a5192890
Freed 0xf14a5192950
Freed 0xf14a5192900
Freed 0xf14a5192840
Freed 0xf14a51926f0
Freed 0xf14a51926a0
Freed 0xf14a5192a80
Freed 0xf14a5192a30
Freed 0xf14a5192af0
Freed 0xf14a5192aa0
Freed 0xf14a51929e0
Freed 0xf14a5192bb0
Freed 0xf14a5192b60
Freed 0xf14a5192c20
Freed 0xf14a5192bd0
Freed 0xf14a5192b10
Freed 0xf14a51929c0
Freed 0xf14a5192970
Freed 0xf14a5192680
Freed 0xf14a5192630
Freed 0xf14a5192dc0
Freed 0xf14a5192d70
Freed 0xf14a5192e30
Freed 0xf14a5192de0
Freed 0xf14a5192d20
Freed 0xf14a5192ef0
Freed 0xf14a5192ea0
Freed 0xf14a5192f60
Freed 0xf14a5192f10
Freed 0xf14a5192e50
Freed 0xf14a5192d00
Freed 0xf14a5192cb0
Freed 0xf14a5193090
Freed 0xf14a5193040
Freed 0xf14a5193100
Freed 0xf14a51930b0
Freed 0xf14a5192ff0
Freed 0xf14a51931c0
Freed 0xf14a5193170
Freed 0xf14a5193230
Freed 0xf14a51931e0
Freed 0xf14a5193120
Freed 0xf14a5192fd0
Freed 0xf14a5192f80
Freed 0xf14a5192c90
Freed 0xf14a5192c40
Freed 0xf14a51932a0
Freed 0xf14a5193250
Freed 0xf14a51915d0
Allocated in total: 2121 bytes
Если вы хотите напечатать, например, A
, ты можешь использовать cJSON_Print
, Пожалуйста, прочитайте документацию здесь.
char *printed_a = cJSON_Print(A);
if (printed_a == NULL) {
goto fail;
}
printf("%s\n", printed_a);
free(printed_a);
Или в этом случае, поскольку вам необходимо в любом случае печатать в буфер для отправки его через UART, вы можете использовать cJSON_PrintPreallocated
:
char buffer[1024];
if (!cJSON_PrintPreallocated(A, buffer, sizeof(buffer), true)) {
goto fail;
}