DaveGamble / cJSON

Ultralightweight JSON parser in ANSI C
MIT License
10.83k stars 3.22k forks source link

Fix the issue#758 (16-digit integers ending with 0 expression issue) #759

Open Hironobu-Ishii opened 1 year ago

Hironobu-Ishii commented 1 year ago

For integers larger than MAX_INT, they are stored internally in doubles, but if there is no fractional part they are expected to be displayed in integer format.

The range of integers that can be safely represented by a double variable is [-(2^53-1), 2^53-1]. Number.MAX_SAFE_INTEGER Number.MIN_SAFE_INTEGER Numbers with no fractional part in this range are expected to be displayed in integer form.

I have tested with x86_64(linux & Win 10), aarch64(linux), armv7l(linux).

Output of sample code before modification

cJSON Version: 1.7.15
{
    "OK1":  1234567890123456,
    "OK2":  1234567890123457,
    "OK3":  1234567890123458,
    "OK4":  1234567890123459,
    "NG1":  1.23456789012346e+15,
    "OK5":  1234567890123461,
    "OK6":  1234567890123462,
    "OK7":  1234567890123463,
    "OK8":  1234567890123464,
    "OK9":  1234567890123465,
    "NG2":  1.23456789012347e+15,
    "OK10": 1234567890123471
}

Output of sample code after modification

cJSON Version: 1.7.15
{
    "OK1":  1234567890123456,
    "OK2":  1234567890123457,
    "OK3":  1234567890123458,
    "OK4":  1234567890123459,
    "NG1":  1234567890123460,
    "OK5":  1234567890123461,
    "OK6":  1234567890123462,
    "OK7":  1234567890123463,
    "OK8":  1234567890123464,
    "OK9":  1234567890123465,
    "NG2":  1234567890123470,
    "OK10": 1234567890123471
}

Sample code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"

static void create_objects(void)
{
    /* declare a few. */
    cJSON *root = NULL;
    char *out;

    root = cJSON_CreateObject();

    cJSON_AddNumberToObject(root, "OK1", 1234567890123456);
    cJSON_AddNumberToObject(root, "OK2", 1234567890123457);
    cJSON_AddNumberToObject(root, "OK3", 1234567890123458);
    cJSON_AddNumberToObject(root, "OK4", 1234567890123459);
    cJSON_AddNumberToObject(root, "NG1", 1234567890123460);
    cJSON_AddNumberToObject(root, "OK5", 1234567890123461);
    cJSON_AddNumberToObject(root, "OK6", 1234567890123462);
    cJSON_AddNumberToObject(root, "OK7", 1234567890123463);
    cJSON_AddNumberToObject(root, "OK8", 1234567890123464);
    cJSON_AddNumberToObject(root, "OK9", 1234567890123465);
    cJSON_AddNumberToObject(root, "NG2", 1234567890123470);
    cJSON_AddNumberToObject(root, "OK10", 1234567890123471);

    /* Print to text */
    if ((out = cJSON_Print(root)) == 0) {
        cJSON_Delete(root);
        exit(EXIT_FAILURE);
    }
    printf("%s\n", out);
    cJSON_Delete(root);
    return;
}

int main(void)
{
    /* print the version */
    printf("cJSON Version: %s\n", cJSON_Version());

    /* Now some samplecode for building objects concisely: */
    create_objects();

    return 0;
}

fixes: #758