JSON编码MySQL查询结果

328

我该如何在MySQL查询结果中使用json_encode()函数?我需要遍历每一行吗,还是可以直接应用于整个结果对象?


1
我知道这是一个非常老的问题。但是没有人展示最简单的替代方法来解决整数显示为字符串的问题。@mouckatron在下面的答案中提供了json_encode()的JSON_NUMERIC_CHECK标志。简单易行,而且非常有效!https://dev59.com/WHM_5IYBdhLWcg3waSX9 - AlexGM
1
关于字符串类型问题,有一个匹配的问题+答案,网址为:https://dev59.com/nofca4cB1Zd3GeqPi3BX - Marcel Ennix
16个回答

540
$sth = mysqli_query($conn, "SELECT ...");
$rows = array();
while($r = mysqli_fetch_assoc($sth)) {
    $rows[] = $r;
}
print json_encode($rows);

函数json_encode需要PHP版本>=5.2和php-json包 - 如这里所提到的
现代PHP版本支持mysqli_fetch_all()函数,可以一次性获取数组
$result = mysqli_query($conn, "SELECT ...");
$rows = mysqli_fetch_all($result); // list arrays with values only in rows
// or
$rows = mysqli_fetch_all($result, MYSQLI_ASSOC); // assoc arrays in rows

print json_encode($rows);

73
建议在选择查询时使用AS来重命名列,以便为公众更改名称,例如SELECT blog_title as title,这样更加清晰,公众也不会知道数据库中确切的列名。 - RobertPitt
14
此代码错误地将所有数值类型编码为字符串。例如,MySQL 中的数字字段 score 在 JSON 值中会被表示为 "12" 而不是 12(请注意引号)。 - Theo
24
@RobertPitt,基于隐藏列名称的安全性是安全性通过混淆 - Tomas
5
@Tomas 确实如此,知道确切的列名会使 SQL 注入攻击变得更加容易。 - Tim Seguine
18
@Tim:如果你已经到了只有列名被知道是防止 SQL 注入的唯一障碍的地步,那么你已经输了,不是吗? - Paolo Bergantino
显示剩余14条评论

44
如果你需要将选定的行放入返回的 JSON 的不同元素中,可以按照以下方式操作:首先,获取像接受的答案中那样的 $rows 数组,然后将其放入另一个数组中,如下所示。
print json_encode(['object_name' => $rows]);

1
+1 这似乎是唯一一个提供与 http://json.org/example 中示例相同格式的 JSON 的答案。 - ban-geoengineering
是的,这个例子为每一行提供了一个键。 - Mar

26

http://www.php.net/mysql_query 中写道 "mysql_query() 返回一个资源(resource)"。

http://www.php.net/json_encode 中提到它可以编码任何值 "除了资源(resource)"。

你需要通过循环遍历并将数据库结果收集到数组中,然后使用 json_encode 函数对该数组进行编码。


2
mysql_query不会返回结果集,这就是mysql_fetch*存在的原因。 - Andy
嗯...是的...这就是在mysql_query和json_encode之间进行迭代的内容。干得好,Watson。 - Hugh Bothwell

14

使用PDO时

使用fetchAll() 将所有行作为关联数组获取。

$stmt = $pdo->query('SELECT * FROM article');
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($rows);

当您的SQL具有参数时:

$stmt = $pdo->prepare('SELECT * FROM article WHERE id=?');
$stmt->execute([1]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($rows);

当您需要重新调整表格时,您可以使用foreach循环并手动构建数组。

$stmt = $pdo->prepare('SELECT * FROM article WHERE id=?');
$stmt->execute([1]);

$rows = [];
foreach ($stmt as $row) {
    $rows[] = [
        'newID' => $row['id'],
        'Description' => $row['text'],
    ];
}

echo json_encode($rows);

使用mysqli时

使用fetch_all()将所有行作为关联数组获取。

$res = $mysqli->query('SELECT * FROM article');
$rows = $res->fetch_all(MYSQLI_ASSOC);
echo json_encode($rows);

当你的SQL有参数时,你需要进行准备/绑定/执行/获取结果。

$id = 1;
$stmt = $mysqli->prepare('SELECT * FROM article WHERE id=?');
$stmt->bind_param('s', $id); // binding by reference. Only use variables, not literals
$stmt->execute();
$res = $stmt->get_result(); // returns mysqli_result same as mysqli::query()
$rows = $res->fetch_all(MYSQLI_ASSOC);
echo json_encode($rows);

当您需要重新设置表的键时,您可以使用foreach循环并手动构建数组。

$stmt = $mysqli->prepare('SELECT * FROM article WHERE id=?');
$stmt->bind_param('s', $id);
$stmt->execute();
$res = $stmt->get_result();

$rows = [];
foreach ($res as $row) {
    $rows[] = [
        'newID' => $row['id'],
        'Description' => $row['text'],
    ];
}

echo json_encode($rows);

使用mysql_* API时

请尽快升级到支持的PHP版本!请认真对待此事。如果您需要使用旧API的解决方案,可以按如下方式进行:

$res = mysql_query("SELECT * FROM article");

$rows = [];
while ($row = mysql_fetch_assoc($res)) {
    $rows[] = $row;
}

echo json_encode($rows);

2
我认为重新键入结果的示例最好使用列别名,因为这样可以避免循环的需要。 - Nigel Ren

8
if ($result->num_rows > 0) {
    # code...
    $arr = [];
    $inc = 0;
    while ($row = $result->fetch_assoc()) {
        # code...
        $jsonArrayObject = (array('lat' => $row["lat"], 'lon' => $row["lon"], 'addr' => $row["address"]));
        $arr[$inc] = $jsonArrayObject;
        $inc++;
    }
    $json_array = json_encode($arr);
    echo $json_array;
} else {
    echo "0 results";
}

6

根据我的经验,在将数组中的根元素命名之前,上述方法是行不通的。在此之前,我无法访问最终的JSON中的任何内容。

$sth = mysql_query("SELECT ...");
$rows = array();
while($r = mysql_fetch_assoc($sth)) {
    $rows['root_name'] = $r;
}
print json_encode($rows);

那就搞定了!


这段混乱的代码将始终只返回一行数据。 - Your Common Sense

6
下面的代码在这里运行得很好!
<?php

$con = mysqli_connect("localhost",$username,$password,"databaseName");

$query = "the query here";
$result = mysqli_query($con,$query);

$rows = array();
while($r = mysqli_fetch_array($result)) {
    $rows[] = $r;
}
echo json_encode($rows);

mysqli_close($con);

3
<?php

define('HOST', 'localhost');
define('USER', 'root');
define('PASS', '');
define('DB', 'dishant');

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$con = mysqli_connect(HOST, USER, PASS, DB);

$sql = "select * from demo ";
$sth = mysqli_query($con, $sql);
$rows = array();
while ($r = mysqli_fetch_array($sth, MYSQLI_ASSOC)) {
    $row_array['id'] = $r;

    array_push($rows, $row_array);
}
echo json_encode($rows);

array_push($rows,$row_array);用于构建数组,否则它会返回while循环中的最后一个值。

这类似于Java中StringBuilderappend方法。


2

抱歉,回答有些晚了,但是:

这个问题有点长,但是:
$sql = 'SELECT CONCAT("[", GROUP_CONCAT(CONCAT("{username:'",username,"'"), CONCAT(",email:'",email),"'}")), "]") 
AS json 
FROM users;'
$msl = mysql_query($sql)
print($msl["json"]);

只是基本的内容:
"SELECT" Select the rows    
"CONCAT" Returns the string that results from concatenating (joining) all the arguments
"GROUP_CONCAT" Returns a string with concatenated non-NULL value from a group

请注意,GROUP_CONCAT()group_concat_max_len 的限制。 - eggyal
2
我不建议任何人使用这种hacky技术。 - mickmackusa

2

我的简单解决方案是停止在数字值周围加上引号...

while($r = mysql_fetch_assoc($rs)){
    while($elm=each($r))
    {
        if(is_numeric($r[$elm["key"]])){
                    $r[$elm["key"]]=intval($r[$elm["key"]]);
        }
    }
    $rows[] = $r;
}   

2
使用JSON_NUMERIC_CHECK标志替代json_encode(getHistory($query), JSON_NUMERIC_CHECK ); - OOM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接