anzusystems / serializer-bundle
序列化组件。
Requires
- php: >=8.2
- ext-json: *
- doctrine/common: ^3.3
- symfony/property-info: ^6.3|^7.0
Requires (Dev)
- doctrine/doctrine-bundle: ^2.10
- doctrine/orm: ^2.13
- nelmio/api-doc-bundle: ^4.13
- slevomat/coding-standard: ^8.14
- symfony/dotenv: ^6.3|^7.0
- symfony/test-pack: ^1.1
- symfony/uid: ^6.3|^7.0
- symplify/easy-coding-standard: ^12.0
- vimeo/psalm: ^5.16
Suggests
- doctrine/orm: Enable EntityIdHandler.
README
一个快速且轻量级的symfony序列化组件。
安装
composer require anzusystems/serializer-bundle
用法
简单通过构造函数注入 AnzuSystems\SerializerBundle\Serializer
,然后
// Serialize object or iterable to json: $this->serializer->serialize($dto); // Deserialize json into object: $this->serializer->deserialize($json, SerializerTestDto::class); // Deserialize json into array of objects: $this->serializer->deserialize($json, SerializerTestDto::class, []); // Deserialize json into collection of objects: $this->serializer->deserialize($json, SerializerTestDto::class, new ArrayCollection());
可以更改 DateTimeInterface
对象的序列化和反序列化默认格式
# config/packages/anzu_systems_serializer.yaml anzu_systems_serializer: date_format: 'Y-m-d\TH:i:s.u\Z'
属性
为了能够(反)序列化对象,该对象的属性(或方法)必须具有 AnzuSystems\SerializerBundle\Attributes\Serialize
属性。
#[Serialize] private string $name; #[Serialize] private int $position; #[Serialize] private DummyDto $dummyDto; #[Serialize] private DateTimeImmutable $createdAt; // Custom date format used by `DateTime`. #[Serialize(type: 'd.m.Y H:i:s')] private DateTimeImmutable $createdAtCustomFormat; // The valueObject must be an instance of `ValueObjectInterface`, to automatically (de)serialize. #[Serialize] private DummyValueObject $dummyValueObject; // The enum must be an instance of `EnumInterface`, to automatically (de)serialize. #[Serialize] private DummyEnum $dummyEnum; // Must be an instance of Symfony\Component\Uid\Uuid, to automatically (de)serialize. #[Serialize] private Uuid $docId; // Type (or discriminator map see below) must be provided for iterables in order to determine how to deserialize its items. #[Serialize(type: DummyDto::class)] private Collection $items; #[Serialize(type: DummyDto::class)] private array $itemsArray; // Serialize collection of entities as IDs ordered by position. #[Serialize(handler: EntityIdHandler::class, type: Author::class, orderBy: ['position' => Criteria::ASC])] protected Collection $authors; // Override type for deserialization based on provided "discriminator" field in json. #[Serialize(discriminatorMap: ['person' => Person::class, 'machine' => Machine::class])] private Collection $items; // Provide type via container parameter name. Example yaml config: // anzu_systems_serializer: // parameter_bag: // AnzuSystems\Contracts\Entity\AbstractUser: App\Entity\User #[Serialize(handler: EntityIdHandler::class, type: new ContainerParam(AbstractUser::class))] protected Collection $users; // (De)serialize a doctrine entity into/from IDs instead of (de)serializing whole object. #[Serialize(handler: EntityIdHandler::class)] private User $user; // Override the name of this property in json. #[Serialize(serializedName: 'stats')] private UserStats $decorated; // Serialize a virtual property (only serialization). #[Serialize] public function getViolations(): Collection
内置处理器
- 基于类型的自动解析处理器
BasicHandler
(标量值和null)DateTimeHandler
(日期格式可通过设置配置)EnumHandler
(字符串和EnumInterface
之间的转换)ObjectHandler
(整个对象的转换,即嵌套)UuidHandler
(转换Symfony Uuids)
- 自定义处理器
EntityIdHandler
(将ID转换为实体及其反转换)ArrayStringHandler
(CSV到数组:将'1,2,3'
或'a, b,c'
转换为[1, 2, 3]
或['a', 'b', 'c']
)
要强制使用特定处理器(覆盖自动解析处理器),只需在 AnzuSerialize
属性中指定处理器即可。
#[Serialize(handler: ArrayStringHandler::class)] private array $ids;
自定义处理器。
要创建自定义处理器,只需扩展 AnzuSystems\SerializerBundle\Handler\Handlers\AbstractHandler
。
例如,在以下示例中,Geolocation类被转换为数组
use AnzuSystems\SerializerBundle\Context\SerializationContext; use AnzuSystems\SerializerBundle\Handler\Handlers\AbstractHandler; final class GeolocationHandler extends AbstractHandler { /** * @param Geolocation $value */ public function serialize(mixed $value, Metadata $metadata, SerializationContext $context): string): array { return [ 'lat' => $value->getLatitude(), 'lon' => $value->getLongitude(), ]; } /** * @param array $value */ public function deserialize(mixed $value, Metadata $metadata): Geolocation { return new Geolocation( (float) $value['lat'], (float) $value['lon'], ); } }
然后只需通过属性强制使用处理器
#[Serialize(handler: GeolocationHandler::class)] private Geolocation $location;
如果您想始终自动使用之前提到的类型 Geolocation
的所有属性并由 GeolocationHandler
处理(无需通过属性强制),请将以下方法添加到处理器中
public static function supportsSerialize(mixed $value): bool { return $value instanceof Geolocation; } public static function supportsDeserialize(mixed $value, string $type): bool { return is_a($type, Geolocation::class, true) && is_array($value); }
如果您想使用多个自动处理器来同时支持同一项功能,您可以通过设置处理器的优先级来选择处理器。在这种情况下,请添加以下方法(优先级较高的将被首先选择)
public static function getPriority(): int { return 3; }
默认情况下,所有处理器的优先级都是0。除了:BasicHandler
具有最高优先级(10) - 它处理简单的标量值,因此通常您希望它首先出现。ObjectHandler
具有最低优先级(-1) - 它处理其他处理器不支持嵌套的可迭代对象/对象。
通过NelmioApiDocBundle自动生成API文档
如果存在NelmioApiDocBundle,则模型描述器将自动注册。Symfony注释也支持并反映在文档中。属性和方法的DocBlock标题也将自动添加为描述。
如果您创建自定义处理器,可以通过添加以下方法到处理器来覆盖生成的描述
use AnzuSystems\SerializerBundle\Metadata\Metadata; use OpenApi\Annotations\Property; public function describe(string $property, Metadata $metadata): array { $description = parent::describe($property, $metadata); $description['type'] = 'object'; $description['title'] = 'Geolocation'; $description['properties'] = [ new Property([ 'property' => 'lon', 'title' => 'Longitude', 'type' => 'float', 'minimum' => -180, 'maximum' => 180, ]), new Property([ 'property' => 'lat', 'title' => 'Latitude', 'type' => 'float', 'minimum' => -90, 'maximum' => 90, ]), ]; return $description; }
有关受支持的描述配置选项的列表,请查看Property属性。
除此之外,您可能还想添加NESTED_CLASS
键来替换描述为整个另一个类的描述
$description[SerializerModelDescriber::NESTED_CLASS] = 'App\Entity\User';
如果您想定义特定对象的数组,那么
$description['items'][SerializerModelDescriber::NESTED_CLASS] = 'App\Entity\User';
最好查看AnzuSystems\SerializerBundle\Handler\Handlers
命名空间,以获取其他处理器如何工作的灵感。
注意事项/要求/功能
- 具有键的迭代将自动(反)序列化为关联数组或索引集合。
- 目前,仅支持json格式。
- 您想要(反)序列化的每个属性都必须有一个公共的getter和setter。
- 属性 $email 的设置器名称示例:
setEmail
- 属性 $email 的获取器名称示例:
getEmail
- 布尔属性的获取器名称示例:
isEnabled
- 属性 $email 的设置器名称示例:
- 您想要序列化(反序列化)的对象的构造函数不能有必需的参数。
- 如果您需要使用必需的参数来实例化一个对象,也可以使用公共静态函数。例如
public static function getInstance(Post $decorated): self { return (new self()) ->setDecorated($decorated) ; }
- 使用
SerializeParam
将请求数据转换为所需的对象。示例
#[Route('/topic', name: 'create', methods: [Request::METHOD_POST])] public function create(#[SerializeParam] Topic $topic): JsonResponse { return $this->createdResponse( $this->topicFacade->create($topic) ); }