【问题标题】:PHP multidimensional array (or object) to JSONPHP 多维数组(或对象)转 JSON
【发布时间】:2012-08-09 18:06:41
【问题描述】:

我有 2 个数据库表。表 2 与表 1 相关。

在 php 中,我正在构建一个多维数组来保存数据键/值。

因为 PHP 需要有唯一的“键”,所以我的 JSON 看起来像这样:

[
{
    "packs": {
        "9": {
            "characters": {
                "40": {
                    "id": "40",
                    "title": "Jack Bauer",
                    "pic": "68bcbe014c.jpg",
                    "gender": "Male"
                },
                "41": {
                    "id": "41",
                    "title": "Chloe O'Brian",
                    "pic": "ffb6acc8e3.jpg",
                    "gender": "Male"
                },
                "42": {
                    "id": "42",
                    "title": "Tony Almeida",
                    "pic": "23f199e223.jpg",
                    "gender": "Male"
                }
            }
        },
        "7": {
            "characters": {
                "7": {
                    "id": "7",
                    "title": "Elvis Presley",
                    "pic": "78300767ad.jpg",
                    "gender": "Male"
                },
                "16": {
                    "id": "16",
                    "title": "Madonna",
                    "pic": "70663a42f7.jpg",
                    "gender": "Male"
                },
                "17": {
                    "id": "17",
                    "title": "Lady Gaga",
                    "pic": "c5099c619b.jpg",
                    "gender": "Male"
                },
                "21": {
                    "id": "21",
                    "title": "Pink Floyd",
                    "pic": "52ddce314a.jpg",
                    "gender": "Male"
                },
                "22": {
                    "id": "22",
                    "title": "Led Zeppelin",
                    "pic": "84cd58ada3.jpg",
                    "gender": "Male"
                },
                "31": {
                    "id": "31",
                    "title": "The Beatles",
                    "pic": "bd22a4d648.jpg",
                    "gender": "Male"
                },
                "32": {
                    "id": "32",
                    "title": "Foo Fighters",
                    "pic": "250fb6ecec.jpg",
                    "gender": "Male"
                },
                "33": {
                    "id": "33",
                    "title": "Bananarama",
                    "pic": "da7c2b56cf.jpg",
                    "gender": "Male"
                },
                "35": {
                    "id": "35",
                    "title": "Boney-M",
                    "pic": "3cbdada38b.jpg",
                    "gender": "Male"
                },
                "38": {
                    "id": "38",
                    "title": "The Spice Girls",
                    "pic": "4751f0fbb7.jpeg",
                    "gender": "Male"
                },
                "39": {
                    "id": "39",
                    "title": "Girls Aloud",
                    "pic": "644dcf71ca.jpg",
                    "gender": "Male"
                }
            }
        },
        "8": {
            "characters": {
                "9": {
                    "id": "9",
                    "title": "Keith Lemon",
                    "pic": "ff6ef10853.jpg.jpg",
                    "gender": "Male"
                },
                "23": {
                    "id": "23",
                    "title": "Fearne Cotton",
                    "pic": "0d038b6516.jpg",
                    "gender": "Male"
                },
                "24": {
                    "id": "24",
                    "title": "Holly Willoughby",
                    "pic": "836fc4184c.jpg",
                    "gender": "Male"
                },
                "30": {
                    "id": "30",
                    "title": "Rufus Hound",
                    "pic": "062bee9602.jpg",
                    "gender": "Male"
                }
            }
        },
        "3": {
            "characters": {
                "5": {
                    "id": "5",
                    "title": "Tom Cruise",
                    "pic": "ff296fafb9.jpg",
                    "gender": "Male"
                },
                "10": {
                    "id": "10",
                    "title": "Linda Lovelace",
                    "pic": "ac1bea43d3.jpg",
                    "gender": "Male"
                },
                "15": {
                    "id": "15",
                    "title": "Gwyneth Paltrow",
                    "pic": "43a22d7240.jpg",
                    "gender": "Male"
                },
                "44": {
                    "id": "44",
                    "title": "Errol Flynn",
                    "pic": "cea17c1275.jpg",
                    "gender": "Male"
                },
                "45": {
                    "id": "45",
                    "title": "Halle Berry",
                    "pic": "752b5c92c5.jpg",
                    "gender": "Male"
                }
            }
        },
        "2": {
            "characters": {
                "4": {
                    "id": "4",
                    "title": "Donald Duck",
                    "pic": "8d367f41b1.jpg",
                    "gender": "Male"
                },
                "6": {
                    "id": "6",
                    "title": "Mickey Mouse",
                    "pic": "8d9629c115.jpg",
                    "gender": "Male"
                },
                "28": {
                    "id": "28",
                    "title": "Pluto",
                    "pic": "fb2c0e2dd0.jpg",
                    "gender": "Male"
                },
                "29": {
                    "id": "29",
                    "title": "Minnie Mouse",
                    "pic": "378760ff77.jpg",
                    "gender": "Male"
                },
                "36": {
                    "id": "36",
                    "title": "Cinderella",
                    "pic": "a7e4888213.jpg",
                    "gender": "Male"
                },
                "37": {
                    "id": "37",
                    "title": "Snow White",
                    "pic": "a9cf05a857.jpg",
                    "gender": "Male"
                }
            }
        },
        "4": {
            "characters": {
                "3": {
                    "id": "3",
                    "title": "Bill Clinton",
                    "pic": "03c6567ddb.jpg",
                    "gender": "Male"
                },
                "11": {
                    "id": "11",
                    "title": "Margaret Thatcher",
                    "pic": "91c9fa9fd0.jpg",
                    "gender": "Male"
                },
                "13": {
                    "id": "13",
                    "title": "David Cameron",
                    "pic": "a689984360.jpg",
                    "gender": "Male"
                },
                "14": {
                    "id": "14",
                    "title": "Nick Clegg",
                    "pic": "3243e298e5.jpg",
                    "gender": "Male"
                },
                "26": {
                    "id": "26",
                    "title": "George Bush JR",
                    "pic": "46296f6b0e.jpg",
                    "gender": "Male"
                },
                "27": {
                    "id": "27",
                    "title": "Ed Milliband",
                    "pic": "66f1449994.jpg",
                    "gender": "Male"
                }
            }
        },
        "5": {
            "characters": {
                "8": {
                    "id": "8",
                    "title": "Stephen Hawking",
                    "pic": "b8c4f17530.jpg",
                    "gender": "Male"
                },
                "18": {
                    "id": "18",
                    "title": "Alan Turing",
                    "pic": "82b4d84e35.jpg",
                    "gender": "Male"
                },
                "19": {
                    "id": "19",
                    "title": "Albert Einstein",
                    "pic": "a6cd74dbaa.jpg",
                    "gender": "Male"
                },
                "34": {
                    "id": "34",
                    "title": "Brian Cox (prof)",
                    "pic": "92b6005de9.jpg",
                    "gender": "Male"
                },
                "43": {
                    "id": "43",
                    "title": "Richard Feynman",
                    "pic": "5de10d1128.jpg",
                    "gender": "Male"
                }
            }
        },
        "6": {
            "characters": {
                "12": {
                    "id": "12",
                    "title": "Jeff Koons",
                    "pic": "8e3ca5f497.jpg",
                    "gender": "Male"
                },
                "20": {
                    "id": "20",
                    "title": "Salvador Dali",
                    "pic": "b5bafb7934.jpg",
                    "gender": "Male"
                },
                "25": {
                    "id": "25",
                    "title": "Rembrandt",
                    "pic": "73e2710029.jpg",
                    "gender": "Male"
                },
                "49": {
                    "id": "49",
                    "title": "Vincent Van Gough",
                    "pic": "6ee455ab28.jpg",
                    "gender": "Male"
                }
            }
        }
    }
}

]

我正在尝试解决我的 iOS 开发人员想要排序的问题...显然 "{"packs":{"9": " 9 是错误的,并且不遵循 key:value JSON 结构。到底如何使用 DB 表 1 中每个结果集的唯一标识符创建正确的 PHP 数组或对象?

结果应该是这样的结构:

data_db_1:1

data_db_2:id data_db_2:标题 data_db_2:图片 data_db_2:性别

data_db_1:2

data_db_2:id data_db_2:标题 data_db_2:图片 data_db_2:性别

data_db_1:3

data_db_2:id data_db_2:标题 data_db_2:图片 data_db_2:性别

data_db_1:4 data_db_2:id data_db_2:标题 data_db_2:图片 data_db_2:性别

看起来像这样:

     {
"id": "9",
"title": "24",
"credits": "100",
"character": [
    {
        "id": "50",
        "title": "Jack Bauer",
        "pic": "68bcbe014c.jpg",
        "gender": "Male"
    },
    {
        "id": "50",
        "title": "Jack Bauer",
        "pic": "68bcbe014c.jpg",
        "gender": "Male"
    },
    {
        "id": "50",
        "title": "Jack Bauer",
        "pic": "68bcbe014c.jpg",
        "gender": "Male"
    },
    {
        "id": "50",
        "title": "Jack Bauer",
        "pic": "68bcbe014c.jpg",
        "gender": "Male"
    }
]

}

我在网上找不到与此相关的分配。我能想到解决它的唯一方法是使用 json_encode() 和 echo 以及一堆 concat 分别从 PHP 数组中创建每个部分。当然 json_encode() 应该能够从一个简单的 php 数组、一个复杂的 php 多维数组或一个 PHP 对象创建正确的 JSON 而不费吹灰之力???


我的 php 函数按要求执行此操作:

$data_ar = output_pack_data($pack_id);

echo "[".json_encode($data_ar)."]";         // first bit of dirty here

function output_pack_data($pack_id = false)
{
global $db;

$output_keys = true; //false;

if($pack_id != false)
{
    $q = "WHERE id='{$pack_id}' AND active = '1'";                                                          // select the relevant pack ID
}
else
{
    $q = "WHERE active='1' ORDER BY order_num ASC";                                                         // select all pack ids
}

$rs = $db->rs("whoami_packs",$q);

$pack_obj = new stdClass();                                                                                 // declare new std class object here......

$data = array();                                                                                            // prep new array to hold the data

while($rs && $r = $db->fetch($rs))                                                                          // loop thorugh each pack id
{
    $pack_obj->packs->id = $r->id;                                                                      // add the pack title
    $pack_obj->packs->title = $r->title;                                                                        // add the pack title
    $pack_obj->packs->credits = $r->credits;                                                                    // add the required credits to access 

    $packs_rs = $db->rs("whoami_characters","WHERE pack_id='{$r->id}' AND active = '1'");                   // get the character data relevant for this pack

    $i=0;

    while($packs_rs && $pack_r = $db->fetch($packs_rs))                                                     // loop through the character data
    {   
        $id = $r->id;

        if($output_keys == false)
        {
            $data['packs'][$r->id]['characters'][$pack_r->id][$pack_r->title][$pack_r->pic][$pack_r->gender] = true;    // build the array
        }
        else
        {
            $data['packs'][$r->id]['characters'][$pack_r->id]['id'] = $pack_r->id;                  // build the array
            $data['packs'][$r->id]['characters'][$pack_r->id]['title'] = str_out($pack_r->title);                   // build the array
            $data['packs'][$r->id]['characters'][$pack_r->id]['pic'] = $pack_r->pic;
            $data['packs'][$r->id]['characters'][$pack_r->id]['gender'] = ($pack_r->gender = 'm') ? "Male" : "Female";
        }
    }
}

return $data;                                                                                               // return the array

}

【问题讨论】:

  • 如果您的开发人员说第一个 JSON 样本是错误的,那么 JSONLint 则不然。
  • 数组看起来如何,如何用表格中的数据填充它?
  • 您的第一个 JSON 看起来不错。您可以使用 php 的 jsonencode() 函数将数组转换为 json。
  • 是的,我知道!!但显然 "6": { 是错误的,即 int 分隔符......到目前为止,这已经争论了一整天。
  • @Nick 我刚刚弄清楚了问题所在。数组必须从零开始索引并连续键入才能正确转换,否则 PHP 的 JSON 编码算法会将其转换为具有数字字符串键的对象。 Consider this。所以正如我之前建议的那样,看起来array_values() 是答案,或者首先构造一个索引为 0 的数组。

标签: php multidimensional-array json


【解决方案1】:

函数中有一些多余的代码。当您有非连续(数字)索引时,json_encode 不会使用 [x,y,z] 编码,而是使用对象表示法。
显然,您的同事希望将 ID 作为每个对象的属性,而不是作为对象的键。因此,只需通过其 id 删除引用数组元素,但首先创建完整的数组,然后通过 $parent[] 将其附加到其父级。通过这种方式,您可以获得一个具有连续数字 id 的数组 -> json_encode() 创建一个数组表示法。
(未经测试,我懒得从原问题中提供的json输出构建sql测试数据)

function output_pack_data($pack_id=false)
{
    global $db;
    $data = array();

    if($pack_id != false) {
        $q = "WHERE id='{$pack_id}' AND active = '1'";
    }
    else {
        $q = "WHERE active='1' ORDER BY order_num ASC";
    }

    $rs_packs = $db->rs("whoami_packs", $q);    
    while($rs_packs && ($rec_pack=$db->fetch($rs_packs)) ) {
        $pack = array(
            'id'=>$rec_pack->id,
            'title'=>$rec_pack->title,
            'credits'=>$rec_pack->credits,
            'characters'=>array()
        );

        $rs_chars = $db->rs("whoami_characters","WHERE pack_id='{$pack->id}' AND active = '1'");
        while($rs_chars && ($rec_char=$db->fetch($rs_chars)) ) {
            $pack['characters'][] = array(
                'id' => $rec_char->id,
                'title' => str_out($rec_char->title),
                'pic' => $rec_char->pic,
                'gender' => 'm'==$rec_char->gender ? "Male" : "Female"
            );
        }
        $data[] = $pack;
    }

    return $data;
}

请阅读https://en.wikipedia.org/wiki/Join_%28SQL%29http://www.w3schools.com/sql/sql_join.asp

【讨论】:

    【解决方案2】:

    对不起,这是评论而不是答案(再次)。

    我认为 iOS 开发人员(比如我自己)的意思是,您使用每个对象的 id 来定义每个对象,而不是键。

    您的示例和开发人员的预期输出都是正确的,但问题在于信息的实际结构。

    如果您前往 http://json.org/example.html 查看 JSON 数据结构的一些示例,可能会更清楚一些。

    让我们用 XML 来看看这个。如果将以下 JSON 转换为 XML:

    [
    {
        "1": {
            "id": "1",
            "title": "Jack Bauer",
            "pic": "68bcbe014c.jpg",
            "gender": "Male"
        }
    },
    {
        "2": {
            "id": "2",
            "title": "Jack Bauer",
            "pic": "68bcbe014c.jpg",
            "gender": "Male"
        }
    }
    ]
    

    您将得到:

    <?xml version="1.0" encoding="UTF-8" ?>
        <1>
            <id>1</id>
            <title>Jack Bauer</title>
            <pic>68bcbe014c.jpg</pic>
            <gender>Male</gender>
        </1>
        <2>
            <id>2</id>
            <title>Jack Bauer</title>
            <pic>68bcbe014c.jpg</pic>
            <gender>Male</gender>
        </2>
    </xml>
    

    简单地说,虽然在这两种情况下都结构正确,但数据放置不正确。 和 节点应该是同一个key,这个原则遵循大多数标准(比如RSS)。

    查看您的开发人员的要求,他想要(在 JSON 和 XML 示例中):

    {
    "character": [
        {
            "id": "1",
            "title": "Jack Bauer",
            "pic": "68bcbe014c.jpg",
            "gender": "Male"
        },
        {
            "id": "2",
            "title": "Jack Bauer",
            "pic": "68bcbe014c.jpg",
            "gender": "Male"
        }
    ]
    }
    

    作为 XML:

    <?xml version="1.0" encoding="UTF-8" ?>
    <character>
        <id>1</id>
        <title>Jack Bauer</title>
        <pic>68bcbe014c.jpg</pic>
        <gender>Male</gender>
    </character>
    <character>
        <id>2</id>
        <title>Jack Bauer</title>
        <pic>68bcbe014c.jpg</pic>
        <gender>Male</gender>
    </character>
    </xml>
    

    第二个例子的结构显然更有效,因为键(字符)定义了每个值,而不是每个值本身的 id。

    【讨论】:

    • "看看你的开发人员的需求,他想要(在 JSON 和 XML 示例中):"LOL
    【解决方案3】:

    所以 json_encode() 似乎会忽略键值,如果它们是一个简单的递增计数器....

    这个函数:

    function output_pack_data($pack_id = false)
    {
    global $db;
    
    $output_keys = true; //false;
    
    if($pack_id != false)
    {
        $q = "WHERE id='{$pack_id}' AND active = '1'";                                                          // select the relevant pack ID
    }
    else
    {
        $q = "WHERE active='1' ORDER BY order_num ASC";                                                         // select all pack ids
    }
    
    $rs = $db->rs("whoami_packs",$q);
    
    $data = array();                                                                                            // prep new array to hold the data
    
    $i = 0;    // AHA!
    
    while($rs && $r = $db->fetch($rs))                                                                          // loop through each pack id
    {
        $data[$i]['pack_id'] = $r->id;  
        $data[$i]['title'] = $r->title;                                                                     // add the pack title
        $data[$i]['credits'] = $r->credits;                                                                 // add the required credits to access 
    
        $chars_rs = $db->rs("whoami_characters","WHERE pack_id='{$r->id}' AND active = '1'");                   // get the character data relevant for this pack
    
        $ii = 0;           // AHA!
    
        while($chars_rs && $char_r = $db->fetch($chars_rs))                                                     // loop through the character data
        {   
            if($output_keys == false)
            {
                $data[$i]['characters'][$ii][$char_r->title][$char_r->pic][$char_r->gender] = true; // build the array
            }
            else
            {
                $data[(int)$i]['characters'][(int)$ii]['id'] = str_out($char_r->id);                    // build the array
                $data[(int)$i]['characters'][(int)$ii]['title'] = str_out($char_r->title);                  // build the array
                $data[(int)$i]['characters'][(int)$ii]['pic'] = $char_r->pic;
                $data[(int)$i]['characters'][(int)$ii]['gender'] = ($char_r->gender = 'm') ? "Male" : "Female";
            }
            $ii++;
        }
    
        $i++;
    }
    
    return $data;                                                                                               // return the array
    

    }

    将返回所需的结果。奇怪的是,文档中没有提到它!哦,好吧,现在排序!希望这可以帮助其他任何人解决这个问题......注意使用 (int) 以确保 $i 或 $ii 计数器是正确的整数。在这种情况下使用 DB ID 将不起作用,它们将被添加到输出中。

    【讨论】:

    • 此链接将清楚地显示它:codepad.org/TadroYeM 如上面(或下面;)的 DaveRandoms 评论中所述)
    【解决方案4】:

    使用选项 JSON_FORCE_OBJECT(自 PHP 5.3.0 起可用,请参阅 here)将强制 json_encode 创建有效的 JSON 对象

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-07
      • 2010-11-11
      • 1970-01-01
      • 2016-03-18
      • 2018-12-18
      相关资源
      最近更新 更多