将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 中将值转换为 int
或 float
(根据需要)更容易。
遍历对象并进行相应的转换。我会使用 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
将 `std::floor()` 和 `std::ceil()` 转换为整数类型是不是总是给出正确的结果?