将数字编码为字符串

PHP json _ encode 函数有一个问题,它将数字编码为字符串,例如。

array('id' => 3)

变成了

"{ ["id": "3", ...)

当 js 遇到这些值时,它将它们解释为字符串,并且数值操作将失败。有人知道如何防止 json_encode将数字编码为字符串吗?谢谢!

160590 次浏览

JSON _ encode 以 JSON 格式序列化一些数据结构,以便通过网络发送。因此,所有内容都将是字符串类型。就像从 $_ POST 或 $_ GET 接收一些参数一样。

如果必须对发送的值进行数值操作,只需首先将它们转换为 int (在 PHP 中使用 Intval ()函数,在 Javascript 中使用 parseInt ()) ,然后执行操作。

PHP json _ encode ()返回一个字符串。

不过,您可以在 js 代码中使用 parseFloat ()或 parseInt () :

parseFloat('122.5'); // returns 122.5
parseInt('22'); // returns 22
parseInt('22.5'); // returns 22

我做了个快速测试:

$a = array(
'id' => 152,
'another' => 'test',
'ananother' => 456,
);
$json = json_encode($a);
echo $json;

如果我没记错的话,这看起来就像你描述的那样?

我得到的结果是:

{"id":152,"another":"test","ananother":456}

因此,在本例中,整数没有转换为字符串。


不过,这可能取决于我们使用的 PHP 版本: 根据 PHP 的版本,已经纠正了两个与 json _ encode 相关的 bug..。

这个测试是用 PHP5.2.6做的; 我用 PHP5.2.9和5.3.0做了同样的测试; 但是我没有另一个5.2. x 版本来测试:-(

您正在使用哪个版本的 PHP? 或者您的测试用例比您发布的示例更复杂?

也许 http://bugs.php.net/上的一个错误报告可能是相关的? 例如,Bug # 40503: json _ encode 整数转换与 PHP 不一致


顺便说一句,也许 Bug # 38680也会让你感兴趣?

我遇到了同样的问题(PHP-5.2.11/Windows)

$json = preg_replace( "/\"(\d+)\"/", '$1', $json );

用数字本身(“42”变成“42”)替换引号中的所有(非负数,整数)数字。

参见 PHP 手册中的注释

下面的测试确认将类型更改为 string 会导致 JSON _ encode ()以 JSON 字符串的形式返回数值(即,用双引号包围)。使用 settype (arr [“ var”] ,“ int”)或 settype ($arr [“ var”] ,“ float”)来修复它。

<?php


class testclass {
public $foo = 1;
public $bar = 2;
public $baz = "Hello, world";
}


$testarr = array( 'foo' => 1, 'bar' => 2, 'baz' => 'Hello, world');


$json_obj_txt = json_encode(new testclass());
$json_arr_txt = json_encode($testarr);


echo "<p>Object encoding:</p><pre>" . $json_obj_txt . "</pre>";
echo "<p>Array encoding:</p><pre>" . $json_arr_txt . "</pre>";


// Both above return ints as ints. Type the int to a string, though, and...
settype($testarr["foo"], "string");
$json_arr_cast_txt = json_encode($testarr);
echo "<p>Array encoding w/ cast:</p><pre>" . $json_arr_cast_txt . "</pre>";


?>

我在处理数据库中的数据时也遇到了同样的问题。基本上,问题在于数组中要在 json 中转换的类型被 PHP 识别为字符串而不是整数。 在我的例子中,我做了一个查询,它从 DB 列计数行返回数据。PDO 驱动程序不将列识别为 int,而是将其识别为字符串。我通过在受影响的列中执行 int 类型的强制转换来解决这个问题。

注意,从 PHP 5.3.3开始,有面旗子用于自动转换数字(options 参数是在 PHP 5.3.0中添加的) :

$arr = array( 'row_id' => '1', 'name' => 'George' );
echo json_encode( $arr, JSON_NUMERIC_CHECK ); // {"row_id":1,"name":"George"}

为了完整起见(因为我还不能添加评论) ,让我也添加这个细节作为另一个答案:

(编辑: 在意识到源数据(例如,在 OP 的情况下,数据库结果集)可能是问题(通过将数字列作为字符串返回) ,并且 json _ encode ()实际上不是问题的根源后读取)

Mysql _ get _ array”的手册页:

返回一个对应于提取行的 字符串数组字符串数组,

还有“ Mysql _ get _ row

返回对应于所获取的 划船

返回的数组中的条目将是字符串。

(我在 phpBB2中使用 DB 类(是的,我知道,它已经过时了!),该类的“ sql _ fetchrow ()”方法使用“ mysql _ get _ array ()”)

没有意识到这一点,我最终还是找到了这个问题,并理解了这个问题! :)

正如 Pascal Martin 在他的后续评论中指出的,我相信一个解决方案可以在源代码中解决“不正确的类型”问题(例如,使用“ Mysql _ field _ type ()”函数并在提取之后立即进行转换,(或者其他提取方法,如“ object”?))总的来说会更好。

$arr = array (‘ var1’= > 100,‘ var2’= > 200) ;
$JSON = JSON _ encode ($arr,JSON _ NUMERIC _ CHECK) ;

但是它只能在 PHP5.3.3上工作 Http://php.net/manual/en/function.json-encode.php#refsect1-function.json-encode-changelog

我也是从 DB (PostgreSQL)中读取数据,所有内容都是字符串。我们循环遍历每一行并使用它来构建最终的结果数组,所以我使用

$result_arr[] = array($db_row['name'], (int)$db_row['count']);

在循环中强制它为一个整数值。当我现在执行 json_encode($result_arr)时,它正确地将其格式化为一个数字。这使您可以控制来自数据库的数字是什么,不是什么。

编辑:

json_encode()函数还可以使用 JSON_NUMERIC_CHECK标志作为它的第二个参数动态执行此操作。您需要小心使用它,不过正如文档(复制到下面)中的这个用户示例所示: http://uk3.php.net/manual/en/function.json-encode.php#106641

<?php
// International phone number
json_encode(array('phone_number' => '+33123456789'), JSON_NUMERIC_CHECK);
?>

然后你得到这个 JSON:

{"phone_number":33123456789}
$rows = array();
while($r = mysql_fetch_assoc($result)) {
$r["id"] = intval($r["id"]);
$rows[] = $r;
}
print json_encode($rows);

只是遇到了同样的问题,数据库将这些值作为字符串返回。

我用这个作为变通办法:

$a = array(
'id' => $row['id'] * 1,
'another' => ...,
'ananother' => ...,
);
$json = json_encode($a);

即将该值乘以1以强制转换为一个数字

希望这对某人有帮助

正如 oli _ arborum 所说,我认为你可以使用 preg_replace来完成这项工作。只要像这样改变命令:

$json = preg_replace('#:"(\d+)"#', ':$1', $json);

这是 php 版本的问题,有了同样的问题升级我的 php 版本到5.6解决了这个问题

将值转换为 int 或 float 似乎可以解决这个问题。例如:

$coordinates => array(
(float) $ap->latitude,
(float) $ap->longitude
);

如果出现任何问题,您可以使用(int) ! ! 它将工作得很好。

所以 Pascal MARTIN在这里没有得到足够的信任。对于具有数百个服务器端函数的现有项目,在每个 JSON 返回上检查数值是不可行的。

我用 php-mysqlnd 代替了 php-mysql,问题就解决了,数字是数字,字符串是字符串,布尔值是布尔值。

我在发送 JSON 的 curl 中遇到了这个问题,它要求一些字段为整数,而其他字段为字符串,但是字符串字段的一些值实际上是数字,所以 JSON _ NUMERIC _ CHECK 无法工作,因为它将所有看起来像数字的东西都转换成了数字。 我找到的解决方案是将表示未来双引号的字符添加到表示字符串值的字段中,在我的例子中,我使用了@,因为我知道在我的数据中不可能有这个字符

$analysis = array(


'SampleAnalysisId'  => $record[3],
'DisplayValue' => '@'.$record[4].'@',
'MeasurementUnit' => '@'.$record[5].'@',
'SampleAnalysisConclusionId'  => $record[6],
'Uncertaint' => '@'.$record[7].'@',
'K' => '',
'QuantificationLimit' => '@'.$record[8].'@',
'DetectionLimit' => '@'.$record[9].'@',
'Veff' => ''

);

在编码之后,我替换了空的双引号,然后替换了双引号的“@”。

$str = json_encode($analysis,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES );
$str = str_replace('@','"',str_replace('",',',',str_replace(':"',':',$str)));

根据我的需要生成一个格式化的 json

[{"SampleAnalysisId":10479,"DisplayValue":"6,3","MeasurementUnit":"mg/L","SampleAnalysisConclusionId":1,"Uncertaint":"0,194463","K":,"QuantificationLimit":"1","DetectionLimit":"0,30","Veff":"}]