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

如何配置JMS Serializer不反序列化未传入的字段?

JMS Serializer处理PATCH请求DTO未传字段的配置方案

场景说明

在PATCH请求的Request DTO中,当请求仅传入部分字段时,未传入的字段会被反序列化为null(因DTO属性初始值为null)。若需要仅更新请求中明确传入的字段,或区分“字段未传入”与“字段传入null”,可通过以下方案实现。


方法一:使用object_to_populate保留初始值

如果希望未传入的字段保持DTO的初始状态(而非被覆盖为null),可在反序列化时传入已初始化的DTO实例,序列化器仅会更新请求中存在的字段:

// 初始化DTO,保留属性初始值
$initialDto = new RequestDTO();

// 反序列化时指定要填充的对象
$updatedDto = $serializer->deserialize(
    $request->getContent(),
    RequestDTO::class,
    'json',
    [
        'object_to_populate' => $initialDto
    ]
);

此方式下,请求中未提及的字段会维持$initialDto的初始值,不会被强制设为null。


方法二:启用字段访问追踪,区分未传入与传入null

若需要明确判断哪些字段是请求中实际传入的(包括传入null的情况),可启用track_visited选项,通过元数据获取字段访问状态:

  1. 反序列化时启用追踪:
$context = new \JMS\Serializer\DeserializationContext();
$context->setAttribute('track_visited', true);

$dto = $serializer->deserialize(
    $request->getContent(),
    RequestDTO::class,
    'json',
    $context
);
  1. 判断字段是否被传入:
$metadataFactory = $serializer->getMetadataFactory();
$classMetadata = $metadataFactory->getMetadataForClass(RequestDTO::class);

// 检查title字段是否被请求传入
$titleWasProvided = $classMetadata->propertyMetadata['title']->isVisited();

返回值说明:

  • true:请求中包含该字段(无论值为null还是其他内容)
  • false:请求中未传入该字段

方法三:字段级自定义赋值逻辑

针对个别字段,可通过@JMS\Accessor注解自定义赋值逻辑,精准控制是否为未传入的字段赋值:

class RequestDTO
{
    /**
     * @JMS\Type("string")
     */
    private ?string $publicId = null;

    /**
     * @JMS\Type("string")
     * @JMS\Accessor(setter="setTitleIfProvided")
     */
    private ?string $title = null;

    public function setTitleIfProvided(?string $title): void
    {
        // 仅当请求明确传入该字段时赋值(结合track_visited可更精准判断)
        $this->title = $title;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 09:43:25