数据库中的JSON编码浮点数是否应该用引号括起来?

时间:2011-03-23 03:06:26

标签: php json pdo

我有以下代码:

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

我使用json_encode将其转换为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"}]

我不希望将LATITUDE和LONGITUDE的值括在引号中。这甚至可能吗?

2 个答案:

答案 0 :(得分:2)

这取决于我相信他们在数据库中的类型。

如果它们是数据库中的varchars或string,则将它们视为字符串。

如果他们是FLOAT的{​​{1}},则他们不应该有引号。

答案 1 :(得分:2)

看起来PDO 始终将数据库结果作为字符串返回,即使它们是数字或浮点数也是如此。

PHP的JSON编码器不执行任何类型的嗅探:如果值保存在PHP字符串中,它将被置于引号中,即使它可以表示为整数或浮点数

你可以通过两种方式解决这个问题。

  1. 在使用json_encode之前,将值明确地转换为浮点数。
  2. 更改JSON的使用者,以便在使用它之前将值转换为浮点数。

  3. 以下是基于getColumnMeta的自动投射示例。首先,让我们创建一个虚拟数据库并插入一些数据。

    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'));
    

    现在我们将为我们的演示证明数据存在:

    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"
    }
    

    让我们看看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
    )
    

    美丽。我也为第1列和第2列做了这个,它分别返回“double”和“string”。现在让我们构建一个列名称的地图来输入:

    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
    )
    
    是的,它反过来了,没关系!现在让我们转换我们的行。

    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"}
    

    多田!你可能想要用一种方便的方法来包装它,每次手动操作都有点毛茸茸。我也可以使用columnCount来获取结果集中的列数而不是计算$row


    过度杀戮?这是一个未经测试的示例,它针对特定的列名称,并在此过程中手动构建哈希数组。

    $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;
    }