在 cjson 的 lua5.3 版本中,所有数字都按 double 类型处理。为了能正确区分整数(integer)和浮点数(double),需要修改 cjson 的源代码。
首先添加类型 T_INT 来表示整数,然后修改 json_next_number_token 函数:扫描字符串中是否包含小数点,若不含则判定为整数类型,将其存为 T_INT;否则仍按 T_NUMBER(double)处理。
static void json_next_number_token(json_parse_t *json, json_token_t *token)
{
char *endptr;
// token->type = T_NUMBER;
//token->value.number
double value = fpconv_strtod(json->ptr, &endptr);
if (json->ptr == endptr)
{
token->type = T_NUMBER;
token->value.number = value;
json_set_token_error(token, json, "invalid number");
}
else
{
//scaning the str has dot-operation
char *start = (char*)json->ptr;
bool is_int = true;
while (start != endptr)
{
if (*start == '.')
{
//this is int
is_int = false;
break;
}
++start;
}
if (is_int)
{
token->type = T_INT;
token->value.integer = (long long)value;
}
else
{
token->type = T_NUMBER;
token->value.number = value;
}
json->ptr = endptr; /* Skip the processed number */
}
return;
}
接着修改 json_process_value 函数,增加对 T_INT 类型的处理,将整数通过 lua_pushinteger 压入 Lua 栈:
/* Handle the "value" context */
static void json_process_value(lua_State *l, json_parse_t *json,
json_token_t *token)
{
switch (token->type) {
case T_STRING:
lua_pushlstring(l, token->value.string, token->string_len);
break;;
case T_NUMBER:
lua_pushnumber(l, token->value.number);
break;;
case T_INT:
lua_pushinteger(l, token->value.integer);
break;;
case T_BOOLEAN:
lua_pushboolean(l, token->value.boolean);
break;;
case T_OBJ_BEGIN:
json_parse_object_context(l, json);
break;;
case T_ARR_BEGIN:
json_parse_array_context(l, json);
break;;
case T_NULL:
/* In Lua, setting "t[k] = nil" will delete k from the table.
* Hence a NULL pointer lightuserdata object is used instead */
lua_pushlightuserdata(l, NULL);
break;;
default:
json_throw_parse_error(l, json, "value", token);
}
}
完成以上修改后,重新编译即可。