ad-astra/serializer

v1.0.0 2024-05-14 20:27 UTC

This package is auto-updated.

Last update: 2024-09-14 21:25:55 UTC


README

快速、简单、可靠的php序列化器,允许将对象转换为指定格式的字符串(目前仅支持json和urlencoded)
以及相反:从字符串(json格式)创建对象 - 反序列化过程

支持

  • 规范化组
  • 循环引用
  • 规范化深度
  • 复合键
  • 数组类型(通过属性)
  • 枚举(包括类型化)
  • 直接访问属性或通过getter/setter

使用方法

基本

假设我们有一个类

class Order
{
    public string $id;
    public float $price;
    public array $products;
}

创建一个实例

$order = new Order();
$order->id = 1;
$order->price = 100.5;

现在,初始化序列化器

$serializer = new Serializer([new ObjectNormalizer()], ['json' => new JsonEncoder()]);

最后一步,序列化为字符串

$str = $serializer->serialize($order, 'json');

$str 将等于json(当然不是格式化的)

{
   "id": "123-abc",
   "price": 100.5,
   "products": null
}

可以将字符串转换为对象,只需指定对象类型

$order = $serializer->deserialize($str, Order::class, 'json');
// output
// object(Order)#11 (2) { ["id"]=> string(7) "123-abc" ["price"]=> float(100.5) ["products"]=> uninitialized(array) }

跳过null值

有用的选项,如果您想省略null值,可以将常量SKIP_NULL_VALUES传递到上下文中,如下所示

$str = $serializer->serialize($order, 'json', context: [ObjectNormalizer::SKIP_NULL_VALUES]);

输出

{
   "id": "123-abc",
   "price": 100.5
}

使用组

您可以通过组指定应该序列化/反序列化的属性
让我们给我们的Order类添加一些组

#[Groups(['group_1', 'group_2'])]
public string $id;

#[Groups(['group_2', 'group_3'])]
public float $price;

现在,如果您将一个组传递给serialise方法,它将处理匹配给定组的属性

$str = $serializer->serialize($order, 'json', ['group_1']);

将输出

{
   "id": "123-abc"
}

因为只有id有属性#Groups与组group_1匹配,
但如果我们传递group_2,我们已经有了idprice

$str = $serializer->serialize($order, 'json', ['group_2']);

将输出

{
  "id": "123-abc",
  "price": 100.5
}

您可以通过传递多个组来指定,任何具有传入组名称之一的属性都将被序列化

$str = $serializer->serialize($order, 'json', ['group_1', 'group_3']);

将输出

{
  "id": "123-abc",
  "price": 100.5
}

有一个特殊组*,如果属性至少有一个任何组,则将被序列化

$str = $serializer->serialize($order, 'json', ['*']);

将输出

{
  "id": "123-abc",
  "price": 100.5
}

这也适用于去规范化过程。

命名

有时需要重命名属性,您可以通过使用Name属性来实现

#[Name('orderId')]
public string $id;

将输出

{
  "orderId": "123-abc"
}

或者您想嵌套一个属性?为了这个目的创建几个对象不是好主意。
只需通过上下文传递SIMPLIFY_COMPOSITE_KEYS,这个选项将使用点符号.拆分指定的
属性名称到嵌套对象!

// Dont forget to pass SIMPLIFY_COMPOSITE_KEYS!!!
$str = $serializer->serialize($order, 'json', ['group_1'], [ObjectNormalizer::SIMPLIFY_COMPOSITE_KEYS]);

将输出

{
  "order": {
    "info": {
      "identifier": {
        "primary": "123-abc"
      }
    }
  }
}

这也适用于去规范化过程。

类型化数组

我们的订单有一些产品

class Product
{
    public string $name;
    public float $price;
}

...

$phone = new Product();
$phone->name = 'Samsung phone';
$phone->price = 100;

$apple = new Product();
$apple->name = 'apple';
$apple->price = 7;

$order->products = [$phone, $apple];

让我们尝试序列化

$str = $serializer->serialize($order, 'json');

输出

{
    "id": "123-abc",
    "price": 100.5,
    "products": [
        {
            "name": "Samsung phone",
            "price": 100
        },
        {
            "name": "apple",
            "price": 7
        }
    ]
}

太棒了!它甚至可以处理嵌套对象(所有属性和组也适用于嵌套对象)。
但是反序列化怎么办?如果数组中是简单类型如整数或字符串,则没有问题,但我们有对象数组!只需通过ArrayType属性指定所需的类型

class Order {
    ...
    #[ArrayType(Product::class)]
    public array $products;
}

...

$order = $serializer->deserialize($str, Order::class, 'json');
//output
//object(Order)#13 (3) { ["id"]=> string(7) "123-abc" ["price"]=> float(100.5) ["products"]=> array(2) { [0]=> object(Product)#17 (2) { ["name"]=> string(13) "Samsung phone" ["price"]=> float(100) } [1]=> object(Product)#21 (2) { ["name"]=> string(5) "apple" ["price"]=> float(7) } } }

就这样!您有了Order对象,其中包含包含Product对象的$products数组!
注意,如果您省略了ArrayType,您将得到简单的关联php数组,因为没有关于数组类型的信息。

序列化和反序列化策略

您甚至可以通过将属性传递到NormalizationContextDenormalizationContext中来指定序列化/反序列化的不同行为。示例

class Order {
...

    #[NormalizationContext(
        new Groups(['group_1']),
        new Name('order.full_price')
    )]
    #[DenormalizationContext(
        new Groups(['group_2']),
        new Name('order_price')
    )]
    public float $price;
...
}

...

$str = $serializer->serialize($order, 'json', ['group_1']);

输出

{
"id": "123-abc",
"full_price": 100.5
}

让我们尝试反序列化

$order = $serializer->deserialize('{"id":"123-abc","order_price":100.5}', Order::class, 'json', ['group_2']);
//output
//object(Order)#11 (2) { ["id"]=> string(7) "123-abc" ["price"]=> float(100.5) ["products"]=> uninitialized(array) }