Symfony 7 MapRequestPayload 嵌套 DTO

问题描述 投票:0回答:1

我想使用 MapRequestPayload 将 JSON 请求解析为嵌套的 DTO。目标是验证 DTO 中的数据。

JSON 示例:

{
    "meta": {
        "locale": "ger",
        "validateOnly": false
    },
    "content": {
        "firstName": "firstName",
        "lastName": "lastName",
        "displayMode": "system",
        "favoriteMandates": [
            {
                "mandateId": "{{mandateId}}",
                "position": 0
            }
        ]
    }
}

“元”始终包含相同的数据集,而内容因端点而异。

更新:我已经与一所大学讨论了这个问题,他希望我研究第二种方法。所以我重新表述了下面的所有内容。

final class UpdateUserSettingsController {
    #[Route(
        path: '/api/v1/user/settings',
        methods: [HttpUpdate::REQUEST]
    )]
public function execute(
        #[MapRequestPayload(acceptFormat: 'json')]
        JsonRequest $request
    ): JsonResponse
    {
            $settingsDTO = new UpdateUserSettingsDto(...$request->content);
            //... do something
     }
}
use Symfony\Component\Validator\Constraints as Assert;
final class JsonRequest
{
    public function __construct(
        #[Assert\Valid]
        public MetaWithAttributes    $meta,
        #[Assert\Type('array')]
        public array                 $content,
    )
    {}
}
use Symfony\Component\Validator\Constraints as Assert;
use CustomConstrains;

final readonly class UpdateUserSettingsDto
{
    public Name $name;
    public FavoriteMandatesCollection $favoriteMandates;

    public function __construct(
        string $firstName,
        string $lastName,
        #[Assert\IsArray] array $favoriteMandates,
        #[CustomConstrains\IsEnumValue(DisplayModeEnum::class)] string $displayMode,
    ) {
        $this->name = Name::fromStrings($firstName, $lastName);
        $this->favoriteMandates = FavoriteMandatesCollection::fromInputArray($favoriteMandates);
        $this->displayMode = DisplayModeEnum::fromString($displayMode);

    }
}

我现在的问题是我需要以某种方式告诉 Symfony 需要检查属性(因此以某种方式使用验证器?)。

如果有人有不同/更好的方法来解决这个问题,而不需要每个端点的请求类和 dto 类,我很乐意尝试一下。

php json symfony
1个回答
0
投票

您需要向数组添加注释,以便映射器了解要使用哪个类进行对象映射并可以应用验证器。

    #[Assert\Type('countable')]
    #[Assert\All(new Assert\Type(type: Contact::class))]
    #[Assert\Valid]
    /**
     * @var Contact[]
     */
    public array          $contacts = [],

我的有效负载示例:

"contacts": [
    {
      "title": "",
      "text": "",
      "href": "",
      "icon": "",
      "sortOrder": 0
    },
    {
      "title": "string",
      "text": "string",
      "href": "string",
      "icon": "string",
      "sortOrder": 0
    }
  ],

输出:

{
  "errors": {
    "contacts[0].title": "This value should not be blank.",
    "contacts[0].text": "This value should not be blank."
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.