如PHP文档中所述,当json_decode
包含长整数的数据结构时,它们将被转换为浮点数。解决方法是使用JSON_BIGINT_AS_STRING
,它将它们保留为字符串。当json_encode
这些值时,JSON_NUMERIC_CHECK
会将这些数字编码回大整数:
$json = '{"foo":283675428357628352}';
$obj = json_decode($json, false, JSON_BIGINT_AS_STRING);
$json2 = json_encode($obj, JSON_NUMERIC_CHECK);
var_dump($json === $json2); // true
使用此方法进行正确的数据往返很容易出错。如果属性包含'123'
,一个应该保留字符串的数字字符串,它将被编码为整数。
我想从服务器获取一个对象,修改一个属性,然后再将整个数据结构放回去。我需要保留原始类型。我不想维护我正在操纵的属性。
这有什么真正的解决方法吗? PHP不再存在大的问题,但json_decode
例程似乎已经过时了。
答案 0 :(得分:4)
只要您的PHP版本实际上可以处理大整数,这意味着如果您正在运行64位版本的PHP (在某些other than Windows上),{{1没有问题:
json_decode
如果您需要处理的整数值超过PHP的$json = '{"foo":9223372036854775807}';
$obj = json_decode($json);
$json2 = json_encode($obj);
var_dump(PHP_INT_MAX, $obj, $json2);
int(9223372036854775807)
object(stdClass)#1 (1) {
["foo"]=>
int(9223372036854775807)
}
string(27) "{"foo":9223372036854775807}"
,那么您只需不能在PHP本机类型中表示它们。因此,你无法解决这个难题;您不能使用本机类型来跟踪正确的类型,也不能替换其他类型(例如字符串而不是整数),因为在编码回JSON时这是不明确的。
在这种情况下,您必须创建自己的跟踪每个属性的正确类型的机制,并使用自定义编码器/解码器处理此类序列化。例如,您需要编写一个自定义JSON解码器,它可以解码为PHP_INT_MAX
等自定义类,您的自定义编码器会识别此类型并将其编码为JSON new JsonInteger('9223372036854775808')
值。
PHP中没有这样的东西。
答案 1 :(得分:0)
对于它的价值,PHP 可以使用bcmath软件包http://php.net/manual/en/book.bc.php支持值> PHP_INT_MAX,但JSON则稍微困难一些。
要回答OP为何不能将值从字符串编码回JSON中的int类型的问题,答案在于转换步骤。读入原始JSON字符串时,它是一个字符串,并逐字节读取。读取值时,它们最初会被读取为字符串(如果是字符串,则为JSON本身),然后根据句点(。)的存在将其转换为正确的类型为int或float。如果该值大于name tag
Art0 sport
Art1 (null)
Art2 sport
Art2 health
,则PHP会将其转换为双精度值,您将失去精度。因此,使用PHP_INT_MAX
会告诉解析器将值保留为字符串,并且不尝试对其进行强制转换,一切都应该很好,即使字符串,该值也应保持不变。>
在进行逆运算时会出现问题,并且执行JSON_BIGINT_AS_STRING
告诉PHP将字符串数字值转换为int / float,但这似乎是在之前写入JSON字符串时发生的,导致值> json_encode($value, JSON_NUMERIC_CHECK)
转换为类似PHP_INT_MAX
的双精度表示形式
请参见https://3v4l.org/lHL62或以下版本:
9.2233720368548e+19
结果:
$bigger_than_max = '{"max": ' . PHP_INT_MAX . '1}'; // appending 1 makes > PHP_INT_MAX
var_dump($bigger_than_max);
var_dump(json_decode($bigger_than_max));
var_dump(json_decode($bigger_than_max, false, 512, JSON_BIGINT_AS_STRING));
var_dump(json_encode(json_decode($bigger_than_max, false, 512, JSON_BIGINT_AS_STRING)));
var_dump(json_encode(json_decode($bigger_than_max, false, 512, JSON_BIGINT_AS_STRING), JSON_NUMERIC_CHECK));
不幸的是,似乎没有一种方法可以解决这个问题,请查看JSON常量http://php.net/manual/en/json.constants.php。我看不到任何允许您将整数值> PHP_INT_MAX写入JSON中的int的方法。
对不起,这找不到解决方案,但希望能消除一些混乱。