Laravel Resource单资源返回时关联数组转为索引数组问题咨询
问题原因
这个问题由Laravel 8的资源序列化逻辑差异和PHP的JSON编码默认行为共同导致:
- 你用
(object)[]初始化的associations是stdClass类型,添加整数键属性时,PHP会将属性存储为整数索引。 - 单资源返回时,
JsonResource会在序列化前递归将stdClass转换为关联数组,你的associations转数组后结构为[2 => ['suppliers' => [], 'offices' => []]],后续Laravel的响应处理会自动将非连续整数键的数组重排为从0开始的索引数组,导致原始整数键丢失。 - 资源集合返回时,
ResourceCollection的序列化逻辑不会对单条资源内的stdClass做强制转数组处理,因此原始的整数键对象结构会被保留。
可用解决方案
方案1:强制
associations保留对象结构
直接用关联数组存储结构,返回前通过JSON编码强制转换为不会被重排的对象,该方案兼容性最好,不会影响其他字段的序列化:$arr = ['id' => $this->id, 'associations' => []]; foreach ($tas as $ta) { $ta_id = $ta->id; $arr['associations'][$ta_id] = ['suppliers' => [], 'offices' => []]; } // 强制转换为对象,避免键被重排 $arr['associations'] = json_decode(json_encode($arr['associations'], JSON_FORCE_OBJECT)); return $arr;方案2:修改单资源响应编码参数
重写Resource类的toResponse方法,为响应添加JSON_FORCE_OBJECT编码参数:public function toResponse($request) { return response()->json($this->resolve($request), 200, [], JSON_FORCE_OBJECT); }注意:该方案会将响应内所有索引数组转为对象,若响应中存在正常的索引数组不建议使用。
方案3:添加占位字符串键
在associations中添加一个字符串类型的占位键,让JSON编码自动识别为关联对象,不会重排整数键,实现最简单:$arr['associations'] = ['_' => null]; // 前端可直接忽略该占位字段 foreach ($tas as $ta) { $ta_id = $ta->id; $arr['associations'][$ta_id] = ['suppliers' => [], 'offices' => []]; }
内容的提问来源于stack exchange,提问作者Inigo EC
相关产品推荐
相关产品推荐

