使用 PHP MySQL 创建嵌套 JSON
Posted
技术标签:
【中文标题】使用 PHP MySQL 创建嵌套 JSON【英文标题】:Creating nested JSON using PHP MySQL 【发布时间】:2018-09-05 10:03:25 【问题描述】:我有一个返回某些字段的 SQL 查询,我正在使用 json_encode()
来获取 JSON 格式的数据,但是我无法以我想要的格式获取它。
php 代码
<?php
function data()
$runDistanceBasedOnCityQuery = "SELECT rc.id, rc.cityId, c.cityName, rc.runId, r.distance, rc.status FROM run_city rc INNER JOIN cities c ON c.id = rc.cityId INNER JOIN run_distance r ON r.id = rc.runId ORDER BY c.cityName";
$runDistanceBasedOnCityResult = $db->prepare($runDistanceBasedOnCityQuery);
$runDistanceBasedOnCityResult->bindParam(":cityId", $cityId, PDO::PARAM_INT);
$runDistanceBasedOnCityResult->execute();
$runDistanceBasedOnCityOutput = $runDistanceBasedOnCityResult->rowCount();
if ($runDistanceBasedOnCityOutput > 0)
while ($runDistanceBasedOnCityRow = $runDistanceBasedOnCityResult->fetch(PDO::FETCH_ASSOC))
$array1 = array($runDistanceBasedOnCityRow['runId'], $runDistanceBasedOnCityRow['distance'], $runDistanceBasedOnCityRow['status']);
for ($i = 0; $i < sizeof($array1); $i++)
$array2 = array("id" => $runDistanceBasedOnCityRow['id'], "runId" => $runDistanceBasedOnCityRow['cityId'], $runDistanceBasedOnCityRow['cityName'] => $array1);
$finalResultRunDistanceBasedOnCity[] = $array2;
$responseRunDistanceBasedOnCity = $finalResultRunDistanceBasedOnCity;
else
$responseRunDistanceBasedOnCity = 'Runs not found';
$result = array("status" => true,
"runsBasedOnCity" => $responseRunDistanceBasedOnCity
);
json($result);
function json($data)
header('Content-Type:application/json');
if (is_array($data))
echo json_encode($data);
?>
我得到的 JSON 格式
"runsBasedOnCity": [
"id": "1",
"runId": "1",
"Bengaluru": [
"2",
"10k",
"1"
]
,
"id": "2",
"runId": "1",
"Bengaluru": [
"1",
"5k",
"1"
]
,
"id": "3",
"runId": "1",
"Bengaluru": [
"5",
"3k",
"0"
]
,
"id": "4",
"runId": "2",
"Chennai": [
"1",
"5k",
"1"
]
,
"id": "5",
"runId": "2",
"Chennai": [
"2",
"10k",
"1"
]
,
"id": "6",
"runId": "2",
"Chennai": [
"4",
"15k",
"1"
]
]
我需要的格式
"runsBasedOnCity": [
"id": "1",
"cityId": "1",
"Bengaluru":
[
runId : "2",
distance : "10k",
status : "1"
,
runId : "1",
distance: "5k",
status : "1"
,
runId : "5",
distance : "3k",
status : "0"
]
,
"id": "2",
"cityId": "2",
"Chennai":
[
runId : "1",
distance : "5k",
status : "1"
,
runId : "2",
distance: "10k",
status : "1"
,
runId : "4",
distance : "15k",
status : "1"
]
我无法找到更好的方法,我对此很陌生,请帮帮我。谢谢!
【问题讨论】:
您真的希望每个城市的属性(包含带有“runId”等的数组)具有不同的名称吗?这似乎不一致且易于使用。将cityName
作为属性并在每个属性上都有runs: [...]
之类的东西不是更好吗?那么 json 会更加更容易使用。
@MagnusEriksson 是的,我需要它,它需要填充下拉列表。
@hushie Chennai 没有任何id
值2
,它有4
、5
和6
。我认为您的预期结果有缺陷,或者您是否想从1
开始为每个城市生成新的id
值?或者,如果总体目标是对城市运行进行分组,那么您可能根本不需要存储 id
s。
@mickmackusa 是的,我注意到了,我已经在我的工作代码中更改了它。我在 cityName 数组中为每次运行添加了 id。
【参考方案1】:
为了有效地对子数组数据进行分组,您应该实现临时键。 cityId
是一个适合分组的值——因为 cityNames
将来可能会故意重复,但 cityId
绝不能在您的数据库表中无意/故意重复。
当遇到每个新的cityId
时,有条件的isset()
调用将确定是否应存储新的/完整的数据集,或者是否应仅将数据附加到子数组中。
我打电话给array_slice()
,因为它减少了不必要的语法/代码膨胀。
遍历所有行后,您可以重新索引$result
数组,将其嵌套在runBasedOnCity
中,并添加status
元素。
我将使用PRETTY_PRINT
展示我的演示,以便更易于阅读,但在您的实际代码中,您应该删除该参数。此外,还有一点建议——尽量让变量名保持简短以提高可读性。
代码:(Demo)
$resultset = [
["id" => "1", "cityId" => "1", "cityName" => "Bengaluru", "runId" => "2", "distance" => "10k", "status" => "1"],
["id" => "2", "cityId" => "1", "cityName" => "Bengaluru", "runId" => "1", "distance" => "5k", "status" => "1"],
["id" => "3", "cityId" => "1", "cityName" => "Bengaluru", "runId" => "5", "distance" => "3k", "status" => "0"],
["id" => "4", "cityId" => "2", "cityName" => "Chennai", "runId" => "1", "distance" => "5k", "status" => "1"],
["id" => "5", "cityId" => "2", "cityName" => "Chennai", "runId" => "2", "distance" => "10k", "status" => "1"],
["id" => "6", "cityId" => "2", "cityName" => "Chennai", "runId" => "4", "distance" => "15k", "status" => "1"]
];
foreach ($resultset as $row)
if (!isset($result[$row["cityId"]]))
$result[$row["cityId"]] = array("id" => $row["id"], "cityId" => $row["cityId"], $row["cityName"] => array(array_slice($row,-3)));
else
$result[$row['cityId']][$row["cityName"]][] = array_slice($row,-3);
if (!isset($result)) // don't need to check rowCount() at all
$result = 'Runs not found';
else
$result = array_values($result);
$result = array("status" => true, "runsBasedOnCity" => $result);
var_export(json_encode($result, JSON_PRETTY_PRINT));
输出:
'
"status": true,
"runsBasedOnCity": [
"id": "1",
"cityId": "1",
"Bengaluru": [
"runId": "2",
"distance": "10k",
"status": "1"
,
"runId": "1",
"distance": "5k",
"status": "1"
,
"runId": "5",
"distance": "3k",
"status": "0"
]
,
"id": "4",
"cityId": "2",
"Chennai": [
"runId": "1",
"distance": "5k",
"status": "1"
,
"runId": "2",
"distance": "10k",
"status": "1"
,
"runId": "4",
"distance": "15k",
"status": "1"
]
]
'
在解释了您希望如何在子数组中保留 id
值之后,解决方案如下:
代码:(Demo)
foreach ($resultset as $row)
if (!isset($result[$row["cityId"]]))
$result[$row["cityId"]] = array("cityId" => $row["cityId"], $row["cityName"] => array(array("id" => $row["id"])+array_slice($row,-3)));
else
$result[$row['cityId']][$row["cityName"]][] = array("id" => $row["id"])+array_slice($row,-3);
if (!isset($result)) // don't need to check rowCount() at all
$result = 'Runs not found';
else
$result = array_values($result);
$result = array("status" => true, "runsBasedOnCity" => $result);
var_export(json_encode($result, JSON_PRETTY_PRINT));
【讨论】:
@hushie 这是一种更简洁的方法。我花了一些时间来编写代码,因为您没有提供现成的输入数组。 @hushie 我添加了第二个代码块,用于按预期存储您的数据(子数组中包含id
值)。
谢谢! :) 这很好用,也很清楚!您提供的解释也很有帮助。以上是关于使用 PHP MySQL 创建嵌套 JSON的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 PHP 和 MySQL 创建 JSON 嵌套子父树(PDO 方法)
如何使用 Spring boot 和 MYSQL 为多级菜单列表创建嵌套 JSON?