【问题标题】:convert mysql result to json with correct types将mysql结果转换为具有正确类型的json
【发布时间】:2015-03-31 10:43:54
【问题描述】:

我知道如何获取 mysql-row 并将其转换为 json:

$row = mysqli_fetch_assoc(mysqli_query($db, "SELECT * FROM table WHERE id=1"));
echo json_encode($row); // it's an ajax-call

但是:

db-row 有不同的类型,如 int、float、string。 通过使用 json_encode() 进行转换,所有结果都是字符串。

有没有比这更好的纠正类型的方法:

$row['floatvalue1'] = 0+$row['floatvalue1'];
$row['floatvalue2'] = 0+$row['floatvalue2'];
$row['intvalue1'] = 0+$row['intvalue1'];

我想遍历键并添加 0,因为:

  • 第一条编码规则:DRY - 不要重复自己

但我不能,因为:

  • 行还有除数字以外的其他类型(字符串、日期)
  • 有很多列
  • 设计处于开发阶段,因此列名称经常更改

提前谢谢并原谅我的英语不好:-)

编辑(回答 Casimir et Hippolyte 的评论问题):

我使用 ajax 调用这个 php 代码来动态获取 sql 值。在我的 javascript 代码中,我使用如下结果:

result['intvalue1'] += 100;

假设 intval1 的 json-result 为 50,计算结果为:

“50100”,而不是 150

【问题讨论】:

  • 你为什么要这么做?
  • 在这种情况下,将您的值转换为 javascript 代码:parseInt、parseFloat。
  • javascript 代码中的同样问题。此外,我通过发送不必要的“-chars”来浪费流量。
  • 您可以在循环中使用mysqli_fetch_field() 从结果集中获取有关每一列的信息,并使用它来了解您是否需要将值转换为数字或将其保留为字符串。但我认为在使用之前在 javascript 中将值转换为 intfloat(根据需要)更容易。
  • 遍历对象并进行相应的转换。我会使用 sscanf

标签: php mysql json


【解决方案1】:

下面的代码只是一个概念证明。它需要封装在函数/方法中并在生产中使用之前进行一些抛光(例如,在循环中调用 mysqli_fetch_field() 并在处理任何行之前存储它返回的对象,而不是每行一次)。

它使用函数mysqli_fetch_field() 来获取有关结果集中每一列的信息,并将那些具有数字类型的列转换为数字。 MYSQLI_TYPE_* 常量的值可以在Mysqli predefined constants 的文档页面中找到。

// Get the data
$result = mysqli_query($db, "SELECT * FROM table WHERE id=1");
$row    = mysqli_fetch_assoc($result);

// Fix the types    
$fixed = array();
foreach ($row as $key => $value) {
    $info = mysqli_fetch_field($result);
    if (in_array($info->type, array(
            MYSQLI_TYPE_TINY, MYSQLI_TYPE_SHORT, MYSQLI_TYPE_INT24,    
            MYSQLI_TYPE_LONG, MYSQLI_TYPE_LONGLONG,
            MYSQLI_TYPE_DECIMAL, 
            MYSQLI_TYPE_FLOAT, MYSQLI_TYPE_DOUBLE
    ))) {
        $fixed[$key] = 0 + $value;
    } else {
        $fixed[$key] = $value;
    }
}

// Compare the results
echo('all strings: '.json_encode($row)."\n");
echo('fixed types: '.json_encode($fixed)."\n");

【讨论】:

  • 谢谢!这就是答案。现在我只需更改此 sn-p 即可转换多个结果。但这将引导我找到解决问题的最佳方法。再次感谢。
  • 谢谢。不过,我看不到代码第 7 行的 $result 来自哪里。是错字吗?
  • @TimSands 实际上,变量$result 丢失了。我想当我将代码片段放入答案时我错误地删除了它(我认为它被用在一个地方并内联它)。我现在修好了。
【解决方案2】:

类似

$row['floatvalue1'] = reset( sscanf ( $row['floatvalue1']  , "%f" ));
$row['floatvalue2'] = reset( sscanf ( $row['floatvalue2']  , "%f" ));
$row['intvalue1'] = reset( sscanf ( $row['intvalue1']  , "%d" ));
json_encode($row);

【讨论】:

  • 感谢这个。但我无法手动执行此操作。有很多列,并且列名称将在接下来的几个月中更改类型和名称,因为使用此 ajax 调用的项目由多个人在 dev 中。
【解决方案3】:

如果您只是想确保您的值对于它们的类型是可操作的,那么您需要首先正确地转换它们的类型。

除非您在服务器端需要它们,否则我会将 json 直接传递到前端并在那里完成工作。

在 Javascript 中,您可以尝试像这样转换数字:

function tryNumber(string){

    return !isNaN( parseInt(string) ) ? parseInt(string) : string;

}

function tryDate(string){

    return !isNaN( new Date(string).getTime() ) ? new Date(string) : string;

}

tryNumber('foo'); // "hello"
tryNumber('24'); // 24
tryDate('bar'); // "bar"
tryDate('December 17, 1995'); // "Sun Dec 17 1995 00:00:00 GMT+0000 (GMT)"

这两行尝试将值转换为Date/Number。如果他们不能被施放,他们将保留String's。

【讨论】:

  • 这是个好方法。我的问题是,我在多个 js 文件中使用 json-results(2 次客户端,一个文件服务器端)。我不想从 sql 调用中提供错误解析的结果并在许多其他地方进行转换。获得 sql-results 后直接使用 php-solution 会更好。
  • @MarcelEnnix 够公平的。 Axiac 的答案可能更适合您的需求。
【解决方案4】:

基于@axiac 答案的 MySQLi OO 版本,它生成包含所有记录的 JSON 数组 ($jsnAll)。在这段代码 sn-p 中,调用 FixSQLType 方法来修复一行。注意,它应该被包裹在一个 try{}catch{} 块中,并且“objMySQLi”已经被实例化了:

         $lcAllRows = array();

         // Make an SQL SELECT statement 
         $SQL = "SELECT * FROM $lcName WHERE $lcWhere";

         // Run the query
         $this->sqlResult =  $this->objMySQLi->query($SQL);

         // Fetch the result
         while( $row = $this->sqlResult->fetch_assoc()){
             $lcCount = count($lcAllRows) ;

             // Call to fix, row 
             $fixedRow = $this->FixSQLType($row);
             $lcAllRows[$lcCount]= $fixedRow;
         }

         $jsnAll = json_encode($lcAllRows);

FixSQLType 方法。这几乎与@axiac 的答案相同,除了对 $this->sqlResult->fetch_field_direct($i) 的调用。 “fetch_field”似乎迷路了,使用“fetch_field_direct”解决了这个问题。

    private function FixSQLType($pRow){
    // FROM https://stackoverflow.com/a/28261996/7571029

    // Fix the types    
    $fixed = array();
    $i = 0;
    foreach ($pRow as $key => $value) {
        $info = $this->sqlResult->fetch_field_direct($i);
        $i++;

        if (in_array($info->type, array(
                MYSQLI_TYPE_TINY, MYSQLI_TYPE_SHORT, MYSQLI_TYPE_INT24,    
                MYSQLI_TYPE_LONG, MYSQLI_TYPE_LONGLONG,
                MYSQLI_TYPE_DECIMAL, 
                MYSQLI_TYPE_FLOAT, MYSQLI_TYPE_DOUBLE
        ))) {
            $fixed[$key] = 0 + $value;
        } else {
            $fixed[$key] = $value;
        }

    }

    return $fixed;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-01
    • 2018-05-09
    • 2016-11-21
    • 2019-09-30
    • 1970-01-01
    • 2021-12-24
    • 2020-11-10
    相关资源
    最近更新 更多