0

我正在尝试使用 CJSON 在我的微控制器代码中解析以下 JSON 字符串。

    {
    "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 的字符串。然后我可以再次运行解析以从 A 中过滤 A1。代码不起作用。它打印“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;
}

我需要分别解析所有字符串及其值,然后打印出来。有人可以请教吗?

问候。

4

1 回答 1

1

您可以通过制作包装器来调试分配器的问题,然后使用 cJSON_InitHooks 安装这些包装器。

我写了一个如何解析您的输入的示例以及一些调试分配器,这应该可以帮助您找到问题。只需将所有printfs 替换为您的函数即可通过 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;
}
于 2018-02-06T12:23:35.610 回答