将mysql结果转换为具有正确类型的json

Posted

技术标签:

【中文标题】将mysql结果转换为具有正确类型的json【英文标题】:convert mysql result to json with correct types 【发布时间】: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 【参考方案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 方法来修复一行。注意,它应该被包裹在一个 trycatch 块中,并且“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://***.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;

【讨论】:

以上是关于将mysql结果转换为具有正确类型的json的主要内容,如果未能解决你的问题,请参考以下文章

通过 PHP 将 Sql 数据库转换为具有正确格式的 JSON,并在 PHP 脚本本身中对值进行排序

如何将 Long 类型的 datetime 转换为具有正确时区的 DateTime

Spark:将 JSON 文件转换为正确的格式

将 `std::floor()` 和 `std::ceil()` 转换为整数类型是不是总是给出正确的结果?

查询Mysql表之后将结果转换为json时如何能够保持字段的原有数据类型?

Mysql 学习总结(86)—— Mysql 的 JSON 数据类型正确使用姿势