PHP怎么判断JSON中的整型 PHP解析json后int类型处理【代码】

3次阅读

php json_decode 默认将数字解析为Float,小整数看似int实为double;大整数需用json_bigint_as_String字符串再手动安全转int,否则精度丢失或溢出。

PHP怎么判断JSON中的整型 PHP解析json后int类型处理【代码】

PHP json_decode整型变浮点或字符串?

PHP 解析 JSON 时,json_decode 默认把所有数字都转成 float(哪怕 JSON 里是 123),除非它能被安全地表示为 int —— 但这个“安全”取决于平台(32/64 位)、是否启用了 JSON_BIGINT_AS_STRING,以及数字大小。比如 9223372036854775807 在 64 位系统上可能变成 int,但 9223372036854775808 就会溢出成 float 或字符串(取决于选项)。

常见错误现象:is_int($data['id']) 返回 false,明明 JSON 里写的是 "id": 1001;或者大 ID(如微信 openid、mongodb ObjectId)被截断或科学计数法显示。

  • 默认不加参数时,json_decode($json) 把所有数字当 float 处理(小整数看似是 int,实则是 float,gettype() 返回 double
  • true 参数(关联数组模式)不会改变数字类型行为,依然 float 优先
  • 想保留整型,必须用 JSON_BIGINT_AS_STRING + 手动转换,或用 filter_var($val, FILTER_VALIDATE_INT) 辅助判断

JSON_BIGINT_AS_STRING 避免大整数丢失

这是最稳妥的起点:让所有超出 PHP 整型范围的数字(比如 64 位整数)直接变成字符串,避免 float 精度丢失或溢出。但注意——它只对“超限”数字生效,小整数(如 123)仍可能被解析为 float。

使用场景:处理微信支付回调、支付宝通知、数据库导出的 bigint 字段、分布式 ID(如 Snowflake)等。

立即学习PHP免费学习笔记(深入)”;

  • json_decode($json, false, 512, JSON_BIGINT_AS_STRING) —— 第三个参数是 depth,不能省略才能传第四个标志位
  • 即使加了该标志,123 还是 float;但 9223372036854775808 会是 string 类型
  • 后续需统一用 filter_var($val, FILTER_VALIDATE_INT) 或正则 /^-?d+$/ 判断是否可转整型,再用 (int)intval() 转换(注意负数和边界)

is_numeric()ctype_digit() 别乱用

很多人用 is_numeric('123') 判整型,但它返回 true 对于 '123.0''1e3' 甚至 ' 123 ' —— 完全不符合“JSON 中原始整型”的语义。而 ctype_digit() 又不支持负数。

真正靠谱的判断逻辑是分层的:

  • 先看类型:如果是 int,直接接受(极少见,除非手动 cast 过)
  • 如果是 string:用 preg_match('/^-?d+$/', $val) 确保纯数字字符串(含负号)
  • 如果是 double:用 fmod($val, 1) === 0.0 && $val >= PHP_INT_MIN && $val 判断是否为“可无损转 int 的 float”
  • 转换时统一用 (int)$val,但注意 (int)9223372036854775808.0 会溢出成 PHP_INT_MAX,所以必须先做范围校验

实际处理建议:封装一个 json_decode_intsafe 函数

别每次手写一判断。一个轻量封装能收敛所有坑:

function json_decode_intsafe(string $json, bool $assoc = true): mixed {     $decoded = json_decode($json, $assoc, 512, JSON_BIGINT_AS_STRING);     if (json_last_error() !== JSON_ERROR_NONE) {         throw new InvalidArgumentException('Invalid JSON: ' . json_last_error_msg());     }     return _convert_numbers_to_int($decoded); }  function _convert_numbers_to_int(mixed $val): mixed {     if (is_array($val)) {         return array_map('_convert_numbers_to_int', $val);     }     if (is_string($val) && preg_match('/^-?d+$/', $val)) {         return (int)$val;     }     if (is_float($val) && fmod($val, 1) === 0.0 && $val >= PHP_INT_MIN && $val <= PHP_INT_MAX) {         return (int)$val;     }     return $val; }

这个函数不改原始 JSON 结构,只对叶子节点数字做安全转换。注意它不处理对象stdClass),如果用了 $assoc = false,得额外递归处理对象属性。

最容易被忽略的是:PHP 的整型范围依赖编译时配置,PHP_INT_MAX 在不同环境可能不同;而 JSON 标准本身不限制数字大小——这意味着你永远要假设输入可能越界,不能只靠 is_intgettype 做断言。

text=ZqhQzanResources