magicsunday/jsonmapper

将JSON映射到PHP

2.3.3 2024-08-02 13:46 UTC

This package is auto-updated.

Last update: 2024-09-02 13:59:04 UTC


README

Latest version License CI

JsonMapper

此模块提供了一个将JSON映射到PHP类的映射器,利用Symfony的属性信息和访问包。

安装

使用Composer

要使用Composer安装,只需从命令行运行以下命令。

composer require magicsunday/jsonmapper

要删除模块,运行

composer remove magicsunday/jsonmapper

使用方法

PHP类

为了确保JSON响应无缝映射到PHP类,您应该仔细准备您的类。为所有属性添加请求的类型注释。

为了确保正确映射集合,属性必须使用phpDocumentor集合注释类型进行注释。集合是一个可以包含其他值的非标量值。

例如

@var SomeCollection<DateTime>
@var SomeCollection<string>
@var Collection\SomeCollection<App\Entity\SomeEntity>

自定义注释

有时可能需要规避设计不良的API的限制。与自定义注释一起,可以解决一些API设计问题(例如,文档与webservice响应不匹配),创建一个干净的SDK。

@MagicSunday\JsonMapper\Annotation\ReplaceNullWithDefaultValue

此注释用于通知JsonMapper,当从JSON获取的值是NULL而不是期望的属性类型时,应使用默认值设置属性。

这可能在API设计不良的情况下是必要的,例如,如果API文档定义了某种类型(例如数组),但是API调用本身在属性没有数据时返回NULL,而不是预期的空数组。

/**
 * @var array<string>
 *
 * @MagicSunday\JsonMapper\Annotation\ReplaceNullWithDefaultValue
 */
public array $array = [];

如果映射尝试将NULL分配给属性,将使用注释的默认值。

@MagicSunday\JsonMapper\Annotation\ReplaceProperty

此注释用于通知JsonMapper替换一个或多个属性。它在类上下文中使用。

例如,如果您想将一个晦涩难懂命名的属性替换为一个更易读的名称。

/**
 * @MagicSunday\JsonMapper\Annotation\ReplaceProperty("type", replaces="crypticTypeNameProperty")
 */
class FooClass
{
    /**
     * @var string
     */
    public $type;
}

实例化

为了创建JsonMapper的实例,您需要向构造函数传递一些参数。构造函数需要一个\Symfony\Component\PropertyInfo\PropertyInfoExtractor的实例和一个\Symfony\Component\PropertyAccess\PropertyAccessor的实例。其他参数是可选的。

首先创建Symfony属性信息提取器的实例。每个提取器列表可以包含任何数量的可用提取器。您还可以创建自己的提取器来调整提取属性信息的过程以满足您的需求。

要使用PhpDocExtractor提取器,您还需要安装phpdocumentor/reflection-docblock库。

use \Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use \Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use \Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use \Symfony\Component\PropertyAccess\PropertyAccessor;

常见的提取器设置

$listExtractors = [ new ReflectionExtractor() ];
$typeExtractors = [ new PhpDocExtractor() ];
$propertyInfoExtractor = new PropertyInfoExtractor($listExtractors, $typeExtractors);

创建属性访问器的实例

$propertyAccessor = PropertyAccess::createPropertyAccessor();

使用第三个参数,您可以将属性名转换器实例传递给映射器。通过这种方式,您可以将JSON属性名转换为PHP类使用的期望格式。

$nameConverter = new \MagicSunday\JsonMapper\Converter\CamelCasePropertyNameConverter();

最后一个构造函数参数允许您向JsonMapper传递一个类映射,以更改默认映射行为。例如,如果您有一个将webservice的JSON响应映射到PHP的SDK,您可以使用类映射通过提供用于映射的替代类列表来覆盖默认映射到SDK的类。

$classMap = [
    SdkFoo::class => Foo::class,
];

创建JsonMapper的实例

$mapper = new \MagicSunday\JsonMapper(
    $propertyInfoExtractor,
    $propertyAccessor,
    $nameConverter,
    $classMap
);

为了处理自定义或特殊类型的对象,将它们添加到映射器中。例如,如果需要对类型为Bar的对象进行特殊处理,则将其添加到映射器中

$mapper->addType(
    Bar::class,
    /** @var mixed $value JSON data */
    static function ($value): ?Bar {
        return $value ? new Bar($value['name']) : null;
    }
);

或添加一个处理程序来映射DateTime值

$mapper->addType(
    \DateTime::class,
    /** @var mixed $value JSON data */
    static function ($value): ?\DateTime {
        return $value ? new \DateTime($value) : null;
    }
);

使用PHP内建的json_decode方法将JSON字符串转换为JSON数组/对象

$json = json_decode('JSON STRING', true, 512, JSON_THROW_ON_ERROR);

调用方法map来执行实际的映射操作,将JSON对象/数组映射到PHP类中。将初始类名传递给该方法,并可选地传递集合类的名称。

$mappedResult = $mapper->map($json, Foo::class, FooCollection::class);

完整的设置可能如下所示

/**
 * Returns an instance of the JsonMapper for testing.
 *
 * @param string[]|Closure[] $classMap A class map to override the class names
 *
 * @return \MagicSunday\JsonMapper
 */
protected function getJsonMapper(array $classMap = []): \MagicSunday\JsonMapper
{
    $listExtractors = [ new ReflectionExtractor() ];
    $typeExtractors = [ new PhpDocExtractor() ];
    $extractor      = new PropertyInfoExtractor($listExtractors, $typeExtractors);

    return new \MagicSunday\JsonMapper(
        $extractor,
        PropertyAccess::createPropertyAccessor(),
        new CamelCasePropertyNameConverter(),
        $classMap
    );
}

开发

测试

composer update
composer ci:cgl
composer ci:test
composer ci:test:php:phplint
composer ci:test:php:phpstan
composer ci:test:php:rector
composer ci:test:php:unit