使用 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 没有任何id2,它有456。我认为您的预期结果有缺陷,或者您是否想从1 开始为每个城市生成新的id 值?或者,如果总体目标是对城市运行进行分组,那么您可能根本不需要存储 ids。 @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 对象

如何使用 PHP 和 MySQL 创建 JSON 嵌套子父树(PDO 方法)

PHP/MySQL - JSON 中的嵌套组

如何使用 Spring boot 和 MYSQL 为多级菜单列表创建嵌套 JSON?

如何使用 laravel 或 mysql 创建嵌套的 json?

如何使用 mysql 本机 json 函数生成嵌套的 json 对象?