earc/serializer

eArc - 显式架构框架 - 序列化组件

1.1 2021-03-19 17:16 UTC

This package is auto-updated.

Last update: 2024-09-20 00:37:23 UTC


README

eArc库的独立轻量级可扩展序列化组件。

尽管这是一个小型库,但它非常强大。只需几行代码,您就可以使用它从CSV导入实体或将它们映射到多个SQL表。

目录

安装

使用composer安装earc序列化库。

$ composer require earc/serializer

基本用法

首先启用earc/di依赖注入组件。

use eArc\DI\DI;

DI::init();

现在您已经准备好序列化一些内容。

use eArc\Serializer\Api\Serializer;

$serializedValue = di_get(Serializer::class)->serialize($value);
$deserializedValue = di_get(Serializer::class)->deserialize($serializedValue);

$value$deserializedValue相同。

默认序列化类型支持DateTimeobjectarraystringintfloatboolnull值类型。

甚至可以序列化递归对象结构。

use eArc\Serializer\Api\Serializer;

class X {
    /** @var Y */
    protected $referenceToY;

    public function __construct()
    {
        $this->referenceToY = new Y($this);
    }
}

class Y {
    /** @var X */
    protected $referenceToX;

    public function __construct(X $x)
    {
        $this->referenceToX = $x;
    }    
}

$serializedValue = di_get(Serializer::class)->serialize(new X());

echo $serializedValue;

这将输出

{"type":"X","value":{"content":{"referenceToY":{"type":"Y","value":{"content":{"referenceToX":{"type":"X","value":{"content":null,"id":57}}},"id":60}}},"id":57}}

$object = di_get(Serializer::class)->deserialize($serializedValue);

$object产生一个指向Y实例的X实例,该实例具有对X的引用。当然,这并不是序列化后的同一实例。它是一个与您在克隆对象时接收到的相同的实例。如果多个引用指向同一实例,则在反序列化后也是如此。您可以通过将多个对象包装在数组中来强制使用相同的实例。

use eArc\Serializer\Api\Serializer;

class Z1 {}
class Z2 {
    public $z1;
}

$classZ1 = new Z1();
$classZ2 = new Z2();
$classZ2->z1 = $classZ1;

$serializedValue = di_get(Serializer::class)->serialize([0 => $classZ1, 1 => $classZ2]);

反序列化的值也将包含对类Z1同一实例的两个引用。

高级用法

earc/serializer的基本用法并不优于原生的PHP serialize/unserialize函数。只有当您需要高级功能时,才应使用earc/serializer。

过滤属性

earc/serializer提供了一种轻松组织属性过滤的方法。扩展SerializerDefaultType并重写filterProperty()方法。只有当此方法返回true时,属性才会被序列化。

use eArc\Serializer\SerializerTypes\SerializerDefaultType;

class MySerializerType extends SerializerDefaultType
{
    public function filterProperty(string $fQCN, string $propertyName): bool
    {
        static $blacklistProperties = [
            MyClass::class => [
                'myPropertyOne' => true,
                'anotherNotSerializedProperty' => true,
            ],
        ];

        return !array_key_exists($fQCN, $blacklistProperties) 
            && !array_key_exists($propertyName, $blacklistProperties[$fQCN]);
    }
}

要使用此过滤器,请将扩展类的对象作为第二个参数。

use eArc\Serializer\Api\Serializer;

$serializerType = di_get(MySerializerType::class);

$serializedValue = di_get(Serializer::class)->serialize($value, $serializerType);
$deserializedValue = di_get(Serializer::class)->deserialize($serializedValue, $serializerType);

通过专用数据类型自定义序列化

在某些情况下,您可能需要完全控制序列化过程。例如,在进一步处理序列化值的情况下,或者如果您的对象/数据需要在序列化或反序列化之前进行特殊处理。专用数据类型为您提供了这种级别的控制,同时保持您的架构整洁。

要创建自己的数据类型,请实现DataTypeInterface

use eArc\Serializer\DataTypes\Interfaces\DataTypeInterface;

class MyDataType implements DataTypeInterface
{
    public function isResponsibleForSerialization(?object $object, $propertyName, $propertyValue): bool
    {
        return is_subclass_of($propertyValue, MyObjectsClassOrInterface::class);
    }

    public function serialize(?object $object, $propertyName, $propertyValue)
    {
        return [
            'type' => MyObjectsClassOrInterface::class,
            'value' => 'Put your serialized Information here.',
        ];
    }
    public function isResponsibleForDeserialization(?object $object, string $type, $value): bool
    {
        return $type === MyObjectsClassOrInterface::class;
    }

    public function deserialize(?object $object, string $type, $value)
    {
        return 'Here you return your deserialized class instance';
    }
}

提示1:serialize()可以返回任何可以被原生PHP函数json_encode()处理的内容。如果不是数组或没有typevalue键,则$type参数将为空字符串,而$value参数将包含序列化值。

提示2:您可以使用FactoryServiceSerializeServiceObjectHashService来执行专用任务。

要使用新数据类型,您需要一个引用新数据类型的序列化类型。或者实现SerializerTypeInterface或扩展SerializerDefaultType并重写getDataTypes()方法。

use eArc\Serializer\SerializerTypes\SerializerDefaultType;

class MySerializerType extends SerializerDefaultType
{
    public function getDataTypes(): iterable
    {
        yield MyDataType::class => null;
        
        foreach (parent::getDataTypes() as $class => $object) {
            yield $class => $object;
        }
    }
}

注意顺序。如果适用多个数据类型,则首先应用位于列表开头的数据类型。

提示:如果您需要使用 earc/di 以外的依赖注入系统来构建 MyDataType 对象,您可以传递对象而不是 null

要使用新的序列化类型而不是默认类型,请将对象作为序列化方法的第二个参数传递。

use eArc\Serializer\Api\Serializer;

$serializerType = di_get(MySerializerType::class);

$serializedValue = di_get(Serializer::class)->serialize($value, $serializerType);
$deserializedValue = di_get(Serializer::class)->deserialize($serializedValue, $serializerType);

提示:您可以使用自己的依赖注入函数(或容器)来构建序列化类型对象。

数据映射

您可以使用 earc/serializer 进行各种数据映射,即使涉及表也是如此。这包括将(嵌套)对象映射到 csv 或 sql,并反向映射。查看示例文件夹以获得印象。

版本

版本 v1.1

  • PHP ^8.0 || ^7.4

版本 v1.0

  • 数据类型可以优先排序
  • 传递序列化类型作为参数,而不是标记数据类型
  • 过滤(白名单或黑名单)属性

版本 v0.1

  • PHP 7.4
  • 额外支持的数据类型
    • DateTime
  • 序列化父类的私有属性

版本 v0.0

首个官方版本

  • 支持的数据类型
    • 对象(类实例)
    • 对象(StdClass)
    • 数组
    • 字符串
    • 浮点数
    • 整数
    • 布尔值
    • null
  • 自定义数据类型
  • 支持递归对象关系的序列化
  • 易于阅读的序列化输出
  • 序列化结构
    • json