简体   繁体   English

是否应使用引号将来自数据库的JSON编码的浮点数括在引号中?

[英]Should JSON-encoded floats from the database be enclosed in quotes?

I have the following code: 我有以下代码:

$stmt = $db->prepare("SELECT LATITUDE, LONGITUDE FROM NODEGEOLOCATION WHERE NODEID = $i");
$stmt->execute();
$path[] = $stmt->fetch(PDO::FETCH_ASSOC);

and I use json_encode to convert this to a JSON format. 我使用json_encode将其转换为JSON格式。 However, I am getting the following JSON: 但是,我得到以下JSON:

[{"route":[{"LATITUDE":"32.224519","LONGITUDE":"-110.947325"},{"LATITUDE":"32.227820","LONGITUDE":"-110.947293"},{"LATITUDE":"32.227843","LONGITUDE":"-110.943865"},{"LATITUDE":"32.230618","LONGITUDE":"-110.943919"},{"LATITUDE":"32.231755","LONGITUDE":"-110.943927"},{"LATITUDE":"32.233836","LONGITUDE":"-110.943963"},{"LATITUDE":"32.233850","LONGITUDE":"-110.946061"},{"LATITUDE":"32.236035","LONGITUDE":"-110.946061"},{"LATITUDE":"32.235993","LONGITUDE":"-110.948083"},{"LATITUDE":"32.235977","LONGITUDE":"-110.952433"}]

I don't want the value of LATITUDE and LONGITUDE to be enclosed in quotes. 我不希望将LATITUDE和LONGITUDE的值括在引号中。 Is this even possible? 这有可能吗?

It depends on their type in the database I believe. 我相信这取决于它们在数据库中的类型。

If they are varchars or string in the database they are treated as strings. 如果它们是数据库中的varchars或字符串,则将它们视为字符串。

If they are FLOAT 's DOUBLE 's, they shouldn't have quotes. 如果它们是FLOATDOUBLE ,则不应使用引号。

It looks like PDO always returns database results as strings, even when they are numbers or floats. 看起来PDO 总是以字符串形式返回数据库结果,即使它们是数字或浮点数也是如此。

PHP's JSON encoder doesn't perform any variety of type sniffing : if the value is held in a PHP string, it gets put in quotes, even if it could be represented as an integer or float. PHP的JSON编码器不执行任何类型的嗅探 :如果将值保存在PHP字符串中,则将其括在引号中,即使它可以表示为整数或浮点数也是如此。

You can deal with this in two ways. 您可以通过两种方式处理此问题。

  1. Expressly cast the value to a float before using json_encode . 在使用json_encode之前,将值明确转换为浮点型。
  2. Alter the consumer of the JSON to cast the value to a float before working with it. 更改JSON的使用者以将值转换为浮点数,然后再使用它。

Here's an example of automatic casting based on getColumnMeta . 这是一个基于getColumnMeta的自动强制转换的示例。 First let's create a dummy database and insert some data. 首先,我们创建一个虚拟数据库并插入一些数据。

php > $pdo = new PDO('sqlite::memory:');
php > $pdo->exec('create table foo(a integer, b float, c text)');
php > $sh = $pdo->prepare('insert into foo(a, b, c) values(?, ?, ?)');
php > $sh->execute(array(1, 2.2, 'Three'));
php > $sh->execute(array(4, 5.55, 'Six'));
php > $sh->execute(array(7, 88.888, 'Nine'));

Now we'll prove that the data is there, for our demo: 现在,对于我们的演示,我们将证明数据已经存在:

php > $sh = $pdo->prepare('select * from foo where a = 4');
php > $sh->execute();
php > $row = $sh->fetch(PDO::FETCH_ASSOC);
php > var_dump($row);
array(3) {
  ["a"]=>
  string(1) "4"
  ["b"]=>
  string(4) "5.55"
  ["c"]=>
  string(3) "Six"
}

Let's see what PDO will tell us about the first column. 让我们看看PDO将告诉我们关于第一列的内容。

php > print_r($sh->getColumnMeta(0));
Array
(
    [native_type] => integer
    [sqlite:decl_type] => integer
    [flags] => Array
        (
        )

    [name] => a
    [len] => 4294967295
    [precision] => 0
    [pdo_type] => 2
)

Beautiful. 美丽。 I did this for columns 1 and 2 as well, which returned "double" and "string" respectively. 我也对列1和2进行了此操作,它们分别返回了“ double”和“ string”。 Now let's build a map of column name to type: 现在,让我们构建一个列名映射以输入:

php > $cols = count($row);
php > $col_types = array(); 
php > while($cols-- > 0) { 
          $col_info = $sh->getColumnMeta($cols);
          $col_types[ $col_info['name'] ] = $col_info['native_type']; 
      }
php > print_r($col_types);
Array
(
    [c] => string
    [b] => double
    [a] => integer
)

Yeah, it's in reverse, doesn't matter! 是的,相反,没关系! Now let's convert our row. 现在,让我们转换行。

php > foreach($row as $k => $v) {
          if($col_types[$k] == 'double')
              $row[$k] = (float)$v;
          if($col_types[$k] == 'integer')
              $row[$k] = (int)$v;
      }
php > var_dump($row);
array(3) {
  ["a"]=>
  int(4)
  ["b"]=>
  float(5.55)
  ["c"]=>
  string(3) "Six"
}
php > echo json_encode($row);
{"a":4,"b":5.55,"c":"Six"}

Tada! 田田! You're probably going to want to wrap this in a convenience method, it's a bit hairy to do every single time by hand. 您可能希望将其包装在一种方便的方法中,每次手动处理都有些麻烦。 I could also have used columnCount to get the number of columns in the result set rather than counting $row . 我也可以使用columnCount来获取结果集中的列数,而不是计算$row


Overkill much? 多杀多了? Here's an untested example that targets the specific column names and builds the array of hashes by hand in the process. 这是一个未经测试的示例,该示例针对特定的列名并在此过程中手工构建哈希数组。

$results = array();
$convert_columns = array( 'b' );
$sh = $pdo->prepare('select * from foo where a = 1');
$sh->execute();
while($row = $sh->fetch(PDO::FETCH_ASSOC)) {
    foreach($convert_columns as $colname)
        $row[$colname] = (float)$row[$colname];
    $results[] = $row;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM