生成 JSON API 响应后,数字数组索引丢失

Posted

技术标签:

【中文标题】生成 JSON API 响应后,数字数组索引丢失【英文标题】:Numeric array index lost once JSON API response is generated 【发布时间】:2019-10-22 09:55:53 【问题描述】:

在生成 JSON REST API 响应时,我在使用 Laravel 5.7 和 php 7.2 时遇到了意外行为。

API 响应中的字段包含一个以数字索引但按如下值排序的数组:

"selections" => array:3 [▼
   3 => "Barton & Guestier/ Spirit/ Brian"
   1 => "Barton & Guestier/ Wine/ Latour"
   2 => "Dom Pérignon/ Effervescent/ Champagne"
]

一旦字段被Illuminate\Http\Resources\Json\JsonResource 类处理以进行编码,索引将从 JSON 输出中剥离,并且数组作为顺序数组返回,如下所示:

"selections": [
    "Barton & Guestier/ Spirit/ Brian",
    "Barton & Guestier/ Wine/ Latour",
    "Dom Pérignon/ Effervescent/ Champagne"
],

如果数组是这样按键排序的,则相同

"selections" => array:3 [▼
   1 => "Barton & Guestier/ Wine/ Latour"
   2 => "Dom Pérignon/ Effervescent/ Champagne"
   3 => "Barton & Guestier/ Spirit/ Brian"

变成了

"selections": [
    "Barton & Guestier/ Wine/ Latour",
    "Dom Pérignon/ Effervescent/ Champagne"
    "Barton & Guestier/ Spirit/ Brian",
],

第一项的索引不再索引31,而是0

问题是我需要保留这些索引,因为它们对应于我的 SQL 数据库中这些条目的 ID。

我能够在Illuminate\Http\Resources\ConditionallyLoadsAttributes 类中找到递归方法filter,它似乎正在使用数字键清除任何元素。 由于它是 Laravel 核心的一部分,因此我无法更改此方法。

    /**
     * Filter the given data, removing any optional values.
     *
     * @param  array  $data
     * @return array
     */
    protected function filter($data)
    
        $index = -1;

        $numericKeys = array_values($data) === $data;

        foreach ($data as $key => $value) 
            $index++;

            if (is_array($value)) 
                $data[$key] = $this->filter($value);

                continue;
            

            if (is_numeric($key) && $value instanceof MergeValue) 
                return $this->mergeData($data, $index, $this->filter($value->data), $numericKeys);
            

            if ($value instanceof self && is_null($value->resource)) 
                $data[$key] = null;
            
        

        return $this->removeMissingValues($data, $numericKeys);
    

当然,我不是第一个尝试返回具有特定顺序或不从索引 0 开始的数值数组的人。这是一个错误吗? 有没有人经历过这种情况并找到解决方法?

【问题讨论】:

无法复制问题3v4l.org/D9u5s 在 JSON/javascript 中,数组只是一个没有明确索引的元素列表。如果需要索引,请使用对象。 另一种解决方案:使用带有元素的数组,其中每个元素是一对[index,value]。 Wiimm 这确实是我正在做的事情(索引 => 值)。问题是 SQL 数据库生成的数值中的索引。您使用对象而不是数组的想法成功了!感谢您为我指明这个方向。 【参考方案1】:

感谢 Wiimm! 使用对象而不是数组是解决方案,并且保留了索引。 使用这种相当不优雅的方法将数组转换为对象json_decode(json_encode($data)),但它确实有效。

更新

问题不是Illuminate\Http\Resources\ConditionallyLoadsAttributes 类中的filter 方法,而是因为在返回数据集之前合并(使用array_merge)。在返回数组(不再是对象)之前删除此操作会正确返回索引。

【讨论】:

以上是关于生成 JSON API 响应后,数字数组索引丢失的主要内容,如果未能解决你的问题,请参考以下文章

从 Api 登录后,我得到了 json 的响应。现在需要将数组长度显示为我的通知图标的计数。怎么做?

ReactJS:Rest API JSON 响应:如何解析

如何获取 JSON 响应数组的所有索引值?

PHP怎么生成去掉中括号的JSON

Golang在json响应中获取数组索引值

Swift Codable:如果 API 将来可能向响应 JSON 添加更多属性,则包括枚举编码键