You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel API空对象被转为空数组的问题及解决方案尝试

Laravel API中空对象被转为空数组的解决方案

问题背景

向Laravel API发送包含空对象的JSON请求时,空对象会被自动转换为空数组,无法原样存入数据库。

请求体示例:

{
    "shouldBeEmptyArray": [],
    "shouldBeEmptyObject": {}
}

控制器直接返回请求内容时,响应结果:

[
    [],
    []
]

问题根源

Laravel的Illuminate\Http\Request类中,json()方法调用json_decode($this->getContent(), true)时,将associative参数设为true,会把所有JSON对象转为关联数组,空对象{}因此被转为空数组[]。框架源码如下:

/**
 * Get the JSON payload for the request.
 *
 * @param  string|null  $key
 * @param  mixed  $default
 * @return \Symfony\Component\HttpFoundation\ParameterBag|mixed
 */
public function json($key = null, $default = null)
{
    if (! isset($this->json)) {
        $this->json = new InputBag((array) json_decode($this->getContent(), true));
    }

    if (is_null($key)) {
        return $this->json;
    }

    return data_get($this->json->all(), $key, $default);
}

提问者曾尝试自定义Request类重写json()方法,但未成功,自定义代码如下:

<?php

namespace App\Http\Requests;

use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\InputBag;

class RequestJsonOverride extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, mixed>
     */
    public function rules()
    {
        return [
            //
        ];
    }

    public function json($key = null, $default = null)
    {
        if (! isset($this->json)) {
            $this->json = new InputBag((array) json_decode($this->getContent(), false));
        }

        if (is_null($key)) {
            return $this->json;
        }

        return data_get($this->json->all(), $key, $default);
    }
}

有效解决方案

方案1:直接获取原始JSON并解析

在控制器或自定义请求类中,跳过Laravel默认的参数解析,直接获取原始请求内容并按需求解析:

// 控制器中获取原始解析结果
$rawPayload = json_decode($request->getContent(), false);

// 此时$rawPayload->shouldBeEmptyObject是stdClass空对象,可直接存入JSON类型的数据库字段
YourModel::create([
    'shouldBeEmptyArray' => $rawPayload->shouldBeEmptyArray,
    'shouldBeEmptyObject' => $rawPayload->shouldBeEmptyObject
]);

方案2:给Request添加自定义宏(全局可用)

在App\Providers\AppServiceProvider的boot()方法中添加自定义宏,用于获取保留原始类型的JSON数据:

use Illuminate\Http\Request;

public function boot()
{
    Request::macro('rawJson', function ($key = null, $default = null) {
        $decoded = json_decode($this->getContent(), false);
        return is_null($key) ? $decoded : data_get($decoded, $key, $default);
    });
}

之后在任意控制器中可直接使用:

$emptyObject = $request->rawJson('shouldBeEmptyObject'); // 得到stdClass空对象

方案3:修正自定义Request类的重写逻辑

原重写代码的问题在于将stdClass对象强制转为数组存入InputBag,导致空对象再次变为空数组。修改为递归保留空对象的结构:

<?php

namespace App\Http\Requests;

use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\InputBag;

class RequestJsonOverride extends Request
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [];
    }

    public function json($key = null, $default = null)
    {
        if (! isset($this->json)) {
            $decoded = json_decode($this->getContent(), false);
            $this->json = new InputBag($this->preserveEmptyObjects($decoded));
        }

        return is_null($key) ? $this->json : data_get($this->json->all(), $key, $default);
    }

    private function preserveEmptyObjects($data)
    {
        if (is_object($data)) {
            $arrayData = (array)$data;
            // 空对象转为(object)[]保留类型
            return empty($arrayData) ? (object)[] : $this->preserveEmptyObjects($arrayData);
        }

        if (is_array($data)) {
            foreach ($data as $k => $v) {
                $data[$k] = $this->preserveEmptyObjects($v);
            }
        }

        return $data;
    }
}

使用时在控制器中注入该自定义请求类即可:

use App\Http\Requests\RequestJsonOverride;

publicpublic function store(RequestJsonOverride $request)
{
    $emptyObject = $request->json('shouldBeEmptyObject'); // 保留空对象类型
}

内容的提问来源于stack exchange,提问作者Nicolas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 10:42:05