跳至正文

导入带格式的数据源(JSON、YAML 等)

可以使用Source帮助程序从格式化源导入数据,该帮助程序会在映射发生之前将数据转换为纯 PHP 结构。

该库为 JSON、YAML 和文件提供原生转换支持:

$source = \CuyZ\Valinor\Mapper\Source\Source::json($jsonString);

// or…

$source = \CuyZ\Valinor\Mapper\Source\Source::yaml($yamlString);

// or…

// File containing valid Json or Yaml content and with valid extension
$source = \CuyZ\Valinor\Mapper\Source\Source::file(
    new SplFileObject('path/to/my/file.json')
);

(new \CuyZ\Valinor\MapperBuilder())
    ->mapper()
    ->map(SomeClass::class, $source);

提供给源的 JSON 或 YAML 可能无效,在这种情况下,可以捕获和操作异常。

try {
    $source = \CuyZ\Valinor\Mapper\Source\Source::json('invalid JSON');
} catch (\CuyZ\Valinor\Mapper\Source\Exception\InvalidSource $exception) {
    // Let the application handle the exception in the desired way.
    // It is possible to get the original source with `$exception->source()`
}

修饰符

有时,源的格式和/或组织方式与值对象不同。修饰符可用于在映射发生之前更改源。

警告

将来可能会删除以下修饰符,以支持映射器转换器,应尽可能使用映射器转换器。修饰符仍然可用于向后兼容。

路径映射

此修饰符可用于使用点表示法更改源数据中的路径。

该映射是使用路径映射的关联数组来完成的。该数组必须以源路径作为键,以目标路径作为值。

源路径使用点符号(例如A.B.C ),并且可以包含一个*表示数组路径(例如A.B.*.C )。

final readonly class Country
{
    /** @var non-empty-string */
    public string $name;

    /** @var list<City> */
    public array $cities;
}

final readonly class City
{
    /** @var non-empty-string */
    public string $name;

    public DateTimeZone $timeZone;
}

$source = \CuyZ\Valinor\Mapper\Source\Source::array([
    'identification' => 'France',
    'towns' => [
        [
            'label' => 'Paris',
            'timeZone' => 'Europe/Paris',
        ],
        [
            'label' => 'Lyon',
            'timeZone' => 'Europe/Paris',
        ],
    ],
])->map([
    'identification' => 'name',
    'towns' => 'cities',
    'towns.*.label' => 'name',
]);

// After modification this is what the source will look like:
// [
//     'name' => 'France',
//     'cities' => [
//         [
//             'name' => 'Paris',
//             'timeZone' => 'Europe/Paris',
//         ],
//         [
//             'name' => 'Lyon',
//             'timeZone' => 'Europe/Paris',
//         ],
//     ],
// ];

(new \CuyZ\Valinor\MapperBuilder())->mapper()->map(Country::class, $source);

自定义源

源只是一个可迭代的,因此很容易创建自定义源。它甚至可以与提供的构建器结合使用。

final readonly class AcmeSource implements IteratorAggregate
{
    private iterable $source;

    public function __construct(iterable $source)
    {
        $this->source = $this->doSomething($source);
    }

    private function doSomething(iterable $source): iterable
    {
        // Do something with $source

        return $source;
    }

    public function getIterator()
    {
        yield from $this->source;
    }
}

$source = \CuyZ\Valinor\Mapper\Source\Source::iterable(
    new AcmeSource([
        'valueA' => 'foo',
        'valueB' => 'bar',
    ])
)->camelCaseKeys();

(new \CuyZ\Valinor\MapperBuilder())
    ->mapper()
    ->map(SomeClass::class, $source);