【问题标题】:PHP / json encode wrongly interprets as associative arrayPHP / json 编码错误地解释为关联数组
【发布时间】:2017-06-27 07:59:11
【问题描述】:

Edit1:问题:我想在 php 中将关联数组转换为索引数组。所以我可以通过 json_encode 将它作为一个数组而不是作为一个对象返回。为此,我尝试填充缺失的键。这里是描述:

遇到一个小问题,需要将一个json_encoded数组作为数组传给js。目前它返回一个对象。我正在使用 Angular,所以我真的需要一个数组。我尽量解释清楚。

$arrNew[0][5][0][0][1]["id"] = 1;
//$arrNew[0][0][0][0][1] = "";
//$arrNew[0][1][0][0][1] = "";
//$arrNew[0][2][0][0][1] = "";
//$arrNew[0][3][0][0][1] = "";
//$arrNew[0][4][0][0][1] = "";
$arrNew[0][5][0][0][1]["name"] = 'Test';
var_dump($arrNew);

所以如果我现在返回它它返回第二个元素作为缺少索引 0-4 的对象原因和缺少索引 0 的第四个元素原因(关联数组 -> 对象)

因此,如果我取消注释该块,它就像一个魅力。现在我遇到的问题不是每次元素 5 有时是 3、4 或其他东西,所以我构建了一个自动添加它们的函数:

$objSorted = cleanArray($arrNew);
function cleanArray($array){
    end($array);
    $max = key($array) + 1; //Get the final key as max!
    for($i = 0; $i < $max; $i++) {
        if(!isset($array[$i])) {
            $array[$i] = '';
        } else {
            end($array[$i]);
            $max2 = key($array[$i]) + 1;
            for($i2 = 0; $i2 < $max2; $i2++) {
            .... same code repeats here for every index

所以如果我 vardump 它返回:

问题: 在 js 方面它仍然是一个对象,我还看到元素没有排序。所以我认为不知何故 PHP 仍然将它视为一个关联数组。任何线索为什么会发生这种情况?键是用循环的索引设置的,并且必须是整数值。

PS:我知道在 JS 中重新编写它是可能的,但几乎每个请求都可以使用大量循环来完成

【问题讨论】:

  • 我不清楚……你需要那里的钥匙5吗?那么它就不能被编码为一个数组。或者您是在问如何摆脱密钥 5 以便将其编码为数组?您究竟期望什么 JSON 数据?
  • @deceze 我需要密钥 5 并通过 json_encode 作为数组返回。所以我尝试用零值填充缺失的键
  • 好吧,这更有意义。可能想edit这个问题澄清一下。
  • 你想在JS中获取数组而不是对象吗?
  • 如果有人能解释为什么这个问题会如此被否决,那就太好了,我的意思是我发布了一个明确的例子。输出和我的期望。不知道我在这里做错了什么。

标签: php arrays json


【解决方案1】:

如果我理解您的问题,您将创建一个稀疏的多维对象数组。因为数组在键中有间隙,json_encode() 在某些级别上生成对象,但您需要它为除最内层之外的所有级别生成数组。

以下函数填充所有数组级别上的缺失键(从0 开始,直到用作数组中的数字键的最大值)。然后它通过键对每个数组进行排序,以确保 json_encode() 将其编码为数组而不是对象。

需要排序,否则json_encode()生成对象;此行为在 json_encode() 文档页面上的 note 中进行了解释:

对数组进行编码时,如果键不是从0开始的连续数字序列,则所有键都编码为字符串,并为每个键值对显式指定。

// If $arr has numeric keys (not all keys are tested!) then returns
// an array whose keys are a continuous numeric sequence starting from 0.
// Operate recursively for array values of $arr
function fillKeys(array $arr)
{
    // Fill the numeric keys of all values that are arrays
    foreach ($arr as $key => $value) {
        if (is_array($value)) {
            $arr[$key] = fillKeys($value);
        }
    }

    $max = max(array_keys($arr));
    // Sloppy detection of numeric keys; it may fail you for mixed type keys!
    if (is_int($max)) {
        // Fill the missing keys; use NULL as value
        $arr = $arr + array_fill(0, $max, NULL);
        // Sort by keys to have a continuous sequence
        ksort($arr);
    }

    return $arr;
}

// Some array to test
$arrNew[0][5][0][0][1]["id"] = 1;
$arrNew[0][3][0][2][1]["id"] = 2;
$arrNew[0][5][0][0][1]["name"] = 'Test';


echo("============= Before ==============\n");
echo(json_encode($arrNew)."\n");

$normal = fillKeys($arrNew);

echo("============= After ==============\n");
echo(json_encode($normal)."\n");

输出:

============= Before ==============
[{"5":[[{"1":{"id":1,"name":"Test"}}]],"3":[{"2":{"1":{"id":2}}}]}]
============= After ==============
[[null,null,null,[[null,null,[null,{"id":2}]]],null,[[[null,{"id":1,"name":"Test"}]]]]]

$arr = $arr + array_fill(0, $max, NULL); 行使用NULL 作为缺失键的值。我认为这是解析数组的最佳 Javascript 代码(您可以使用 if (! arr[0]) 来检测虚拟值)。

您可以使用空字符串 ('') 代替 NULL 来获得更短的 JSON:

[["","","",[["","",["",{"id":2}]]],"",[[["",{"id":1,"name":"Test"}]]]]]

但它需要在 JS 端稍长的代码来检测虚拟值 (if (arr[0] != ''))。

【讨论】:

  • 首先完成所有工作,实际上,如果您阅读我的问题,我已经有了一个填补空白的函数。问题是它仍然将其解释为关联数组,并以此方式作为 js 中的对象。甚至在 ksort 之前,键现在也已正确排序。有趣的是,如果我添加不会改变任何东西的 ksort,它实际上会将它从关联数组转换为数字数组,这比在 JS 中有效。我不知道为什么,但真的很高兴。我永远不会尝试对已经排序的数组进行排序:D 啊,我肯定也会使用带有 NULL 的提示。
  • 我看到你已经有一个填补空白的功能,我只是不喜欢它;-) 我的作品适用于任意数量的级别。在ksort() 之前,键是:5、0、1、2、3、4(您可以在问题中发布的var_dump() 中看到它们)。它们不是"a continuous numeric sequence starting from 0"json_encode() 产生一个对象来保持它们的解码顺序。在ksort() 之后,它们是:0、1、2、3、4、5,并且可以安全地在编码时忽略它们。将其编码为数组会在解码时产生相同的结果。
  • 我重建了它以在填充孔后添加它,所以它有 0、1、2、3、4、5,仍然不想工作,但 ksort() 修复了它。无论如何都会将其重建为您的填充算法。喜欢它也超过我的:)
猜你喜欢
  • 1970-01-01
  • 2015-09-20
  • 2015-10-27
  • 1970-01-01
  • 2012-10-13
  • 1970-01-01
  • 1970-01-01
  • 2017-06-22
  • 1970-01-01
相关资源
最近更新 更多