json_encode 不保留顺序
Posted
技术标签:
【中文标题】json_encode 不保留顺序【英文标题】:json_encode not preserving order 【发布时间】:2014-01-21 15:28:37 【问题描述】:我有一个多维数组,在 php 中:
Array
(
[1] => Array
(
[19] => Array
(
[type] => 2
)
[6] => Array
(
[type] => 4
)
[12] => Array
(
[type] => 3
)
)
)
当我通过以下方式在 javascript 中对这个数组进行 json_encode:
var jsonArray = <?php echo json_encode($above_array); ?>;
我明白了:
Object
(
[1] => Object
(
[6] => Object
(
[type] => 2
)
[12] => Object
(
[type] => 4
)
[19] => Object
(
[type] => 3
)
)
)
我想通过 id 保留第一个订单而不是第二个订单。
【问题讨论】:
我如何保留第一个订单? 使用其他东西作为键(例如key_1,key_2,key3),这样你就可以在解码json后进行排序 php.net/manual/en/function.json-encode.php#107616 JSON 对象是无序的键值映射。 数组 是有序列表。任你选,Javascript/JSON 没有 ordered 映射。 如果你想保留顺序,你需要一个数组,而不是一个对象。您需要生成一个如下所示的结构:[[19, type: 2], [9, type: 2], [6, type: 4], [12, type: 3]]
,即一个数组数组,其中每个嵌套数组包含两个元素,“索引”和type
对象。
【参考方案1】:
问题是在 JavaScript 中只有数组是有序的,对象不是。
如果你有类似的东西:
array(
array(
'type' => 2
'id' => 6
),
array(
'type' => 4
'id' => 12
),
array(
'type' => 3
'id' => 19
)
)
然后在您的 JavaScript 中,您将拥有一个对象数组,并且该数组将保持其顺序。
它乱序的原因是因为你的数组的索引不是从 0 开始的,键没有按顺序排列并且键中有间隙。因此,在编码时,PHP 将其转换为对象而不是数组。
【讨论】:
【参考方案2】:*** 上有一个问题 Does JavaScript Guarantee Object Property Order? 简而言之,答案是否定的,它没有。所以在将 PHP 数组转换为 Javascript 对象时,不会保留键顺序。
PHP 和 Javascript 中数组的主要区别在于后者只能保存从零开始的连续整数键。因此,并非总是可以将 PHP 数组转换为 Javascript 数组。 我们来看几个例子:
// example 1
echo json_encode(array(0 => 'a', 1 => 'b')) // outputs ["a","b"]
// example 2
echo json_encode(array(0 => 'a', 3 => 'b')) // outputs "0":"a","3":"b"
// example 3
echo json_encode(array(3 => 'b', 0 => 'a')) // outputs "3":"b","0":"a", but in Javascript the key order will be the same as in example 2
-
在第一个示例中,
json_encode
将 PHP 数组转换为相同的 Javascript 数组。
在第二个示例中,它转换为对象,因为键顺序不是连续的。
在第三个示例中,它也转换为对象。但是在 Javascript 中,对象 2 和 3 将是相同的,具有相同的键顺序,即使键以不同的顺序列出。所以不是 json_encode
函数没有保留键顺序,而是 Javascript 本身。
回到我们的问题:如何将 PHP 数组传递给 Javascript 并保留键顺序? 一种方法是将 PHP 键值对包装到数组中:
// original array:
array(
3 => 'b',
0 => 'a'
)
// must be converted to:
array(
array(3, 'b'),
array(0, 'a')
)
那么json_encode
将产生以下Javascript数组:
[
[3,"b"],
[0,"a"]
]
最后一部分是在 Javascript 中遍历这样的数组:
var php_encoded_array = [
[3,"b"],
[0,"a"]
];
for (var i=0; i < php_encoded_array.length; i++)
var rec = php_encoded_array[i],
key = rec[0],
value = rec[1];
console.log(key + ': ' + value);
// It will output:
// 3: b
// 0: a
// Which is the exact same order as in the PHP array
这种方法也与非整数键兼容。
这是在 PHP 端转换数组的代码(由 pr1001 在类似问题中建议)。它适用于一维数组。
array_map(
function($key, $value) return array($key, $value); ,
array_keys($data),
array_values($data)
)
下面是多维数组的递归函数实现:
function array_preserve_js_order(array $data)
return array_map(
function($key, $value)
if (is_array($value))
$value = array_preserve_js_order($value);
return array($key, $value);
,
array_keys($data),
array_values($data)
);
【讨论】:
像魅力一样工作!【参考方案3】:要保持 PHP 数组的顺序,请使用 array_values()
函数。
<?php $php_array = array_values($php_array); ?>
var jsonArray = JSON.parse('<?php echo json_encode($php_array); ?>');
【讨论】:
以上是关于json_encode 不保留顺序的主要内容,如果未能解决你的问题,请参考以下文章
serialize/json_encode 到一个字段或将原始数据保留在 db 的多个字段中?