在 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);
	}
}

完成以上修改后,重新编译即可。