首页 > 解决方案 > 如何实现从 CSV 文件创建多个资源?

问题描述

语境

我正在尝试在 API 平台中实现自定义端点,以从 CSV 创建资源集合。

我做了一个 DTO 类EntitiesMultipleRecords来存储 CSV 记录。每条记录都是一个实体的关联属性数组。我的用例需要自定义规范EntitiesMultipleRecordsCSVDenormalizer器。它设置为更改内置 Symfony 的输出并非CsvEncoder规范化为我的 DTO 类。DataTransformerMultipleEntitiesCSVDataTransformer处理向实体数组的转换。DataTransformer 和自定义反序列化器都注册为服务,反规范化器服务标记为symfony.normalizer.

作为验证整个过程的快速测试,我整理了这个正确处理它的例程:

$decoder = new Serializer(
    [new EntitiesMultipleRecordsCSVDenormalizer()],
    [new CsvEncoder([CsvEncoder::DELIMITER_KEY => ';'])]
);
$content = file_get_contents(
    "{$kernel->getProjectDir()}/tests/_data/imports/dna/dna_import.csv"
);
$results = $decoder->deserialize($content, EntitiesMultipleRecords::class, 'csv');

$trans = new MultipleEntitiesCSVDataTransformer($em);
$entities = $trans->transform($results, Dna::class);
// got an array of DNA entities
// do some persisting and return response

问题 :

所以所有单独的部分一起工作,但我想不出一种方法来配置 API 平台以按预期方式使用它们

我找到了这个例子,并试图重现类似的配置(下面的代码示例)。

但是,在使用 swagger UI 测试端点时出现以下错误:

App\\Controller\\API\\ImportCSVAction::__invoke(): 
Argument #1 ($data) must be of type App\\DTO\\EntitiesMultipleRecords, App\\Entity\\Dna given

我显然在这里遗漏了一些东西。__invoke将方法参数的类型提示更改为Dna不会修复任何问题,实体为空。此外,如果可以直接使用反序列化的实体,则需要一个数组Dna,而不是单个数组。

我猜想甚至没有使用反序列化管道,即使我将资源设置为使用我的 DTO 作为输入类。

资源配置:

 * @ApiResource(
 *     collectionOperations={
 *           "import": {
 *                  "method": "POST",
 *                  "path": "/dnas/import",
 *                  "input": EntitiesMultipleRecords::class,
 *                  "controller": ImportCSVAction::class,
 *                  "input_formats": {"csv": {"text/csv"}},
 *              }
 *     },
 * )
 class Dna { 
     //...
 }

这是动作类:

namespace App\Controller\API;
use App\DTO\EntitiesMultipleRecords;
/**
 * @param EntitiesMultipleRecords $data
 */
class ImportCSVAction {
    public function __invoke(EntitiesMultipleRecords $data) {
        dump($data);
        return $data;
    }
}

失败的请求:

curl -X 'POST' \
  'https://localhost:8000/api/dnas/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/csv' \
  -d 'the content of dna_import.csv which is a correctly formed CSV string with ; delimiter'

标签: api-platform.com

解决方案


推荐阅读