peekandpoke/slumber

通过注解进行序列化

v1.1.1 2018-02-26 12:57 UTC

README

Code Coverage Scrutinizer Code Quality Build Status

Slumber

什么是Slumber?它是一个将对象数据映射到数组以及反向映射的工具。

它允许您轻松地将领域模型映射到JSON。或者将JSON映射到领域模型类。

Slumber使用Doctrine注解。注解用于标记哪些类的属性需要映射以及如何映射。

(PHP5.6兼容性直到v0.4.x)

基本示例

Slumber注解类的“标志”是这些注解

use PeekAndPoke\Component\Slumber\Annotation\Slumber;

class MyClass {

    /**        
     * @Slumber\AsString()
     */
    private $name;

    /**
     * @Slumber\AsInteger()
     */
    private $age;

    /**
     * @Slumber\AsDecimal()
     */
    private $height;

    /**
     * @Slumber\AsObject(Address::class)
     */
    private $address;
}


echo json_encode($codec->slumber(new MyClass()); 

可能输出以下内容

{
  "name": "Bart",
  "age": 10,
  "height": 1.10,
  "address": {
    "city": "Springfield",
    "country": "USA"
  }
}

入门指南

数组编解码器示例

为了获得数组编解码器,我们需要设置它

// we need an instance of a PSR-11 container (should be provided by the application)
$di = ...;

// we need a doctrine annotation reader (you should use caching, ideally APCU as cache)
$annotationReader = new AnnotationReader();

// SLUMBER: we need a configuration reader (you should wrap the reader with CachedEntityConfigLookUp for good performance)
$reader = new AnnotatedEntityConfigReader($di, $annotationReader, new ArrayCodecPropertyMarker2Mapper());

// SLUMBER: finally we get the codec
$codec = new ArrayCodec($reader);

// then use it for serializating objects into array data
$data = $codec->slumber(new Person());

// or use if for de-serializating array data back into objects
$person = $codec->awake($data, Person::class);

映射

为了完全控制序列化和反序列化,有一组可以使用的注解。

映射标量

您可以在这里找到所有映射器的实现

Slumber\AsBool()

映射值到布尔值。

class C {
  /**
   * @Slumber\AsBool()
   */
  private $val = true;
}

映射到

{
  "val": true
}
class C {
  /**
   * @Slumber\AsBool()
   */
  private $val = 0;
}

映射到

{
  "val": false
}

相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里

Slumber\AsDecimal()

映射值到浮点值。

class C {
  /**
   * @Slumber\AsDecimal()
   */
  private $val = 1.23;
}

映射到

{
  "val": 1.23
}
class C {
  /**
   * @Slumber\AsDecimal()
   */
  private $val = "abc";
}

映射到

{
  "val": 0
}

相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里

Slumber\AsInteger()

映射值到浮点值。

class C {
  /**
   * @Slumber\AsInteger()
   */
  private $val = 1.23;
}

映射到

{
  "val": 1
}
class C {
  /**
   * @Slumber\AsInteger()
   */
  private $val = "abc";
}

映射到

{
  "val": 0
}

相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里

Slumber\AsIs()

映射值保持不变。

class C {
  /**
   * @Slumber\AsAs()
   */
  private $val = 1.23;
}

映射到

{
  "val": 1.23
}
class C {
  /**
   * @Slumber\AsIs()
   */
  private $val = "abc";
}

映射到

{
  "val": "abc"
}

相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里

Slumber\AsString()

映射值到浮点值。

class C {
  /**
   * @Slumber\AsString()
   */
  private $val = 1.23;
}

映射到

{
  "val": "1.23"
}
class C {
  /**
   * @Slumber\AsString()
   */
  private $val = "abc";
}

映射到

{
  "val": "abc"
}

相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里

映射嵌套对象

Slumber\AsObject()

映射到和从嵌套对象。

class B {
  /**
   * @Slumber\AsString()
   */
  private $name;
}

class C {
  /**
   * @Slumber\AsObject(B::class)
   */
  private $val = new B();   // syntax error ... new B() only for demonstration purposes
}

映射到

{
  "val": {
    "name": "..."
  }
}
class C {
  /**
   * @Slumber\AsString()
   */
  private $val = "abc";
}

映射到

{
  "val": null
}

相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里

Slumber\AsEnum()

映射值到枚举值。

为此,我们需要一个枚举类。有关枚举的详细信息,请参阅这里

class Enum extends Enumerated {

    /** @var Enum */
    public static $ONE;
    /** @var Enum */
    public static $TWO;
}

Enum::init();
class C {
  /**
   * @Slumber\AsEnum(Enum::class)
   */
  private $val = Enum::$ONE;
}

映射到

{
  "val": "ONE"
}
class C {
  /**
   * @Slumber\AsEnum(Enum::class)
   */
  private $val = "abc";
}

映射到

{
  "val": null
}

相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里

映射集合、列表、键值对

Slumber\AsList()

映射值到列表(无索引的数组)。

注解期望嵌套注解来控制集合内元素的形状。

class C {
  /**
   * @Slumber\AsList(
   *   @Slumber\AsDecimal()
   * )
   */
  private $val = [1.1, 2.2, 3.3];
}

映射到

{
  "val": [1.1, 2.2, 3.3]
}
class C {
  /**
   * @Slumber\AsList(
   *   @Slumber\AsDecimal()
   * )
   */
  private $val = ["a": 1.1, "b": 2.2, "c": 3.3];
}

映射到

{
  "val": [1.1, 2.2, 3.3]
}

相同的行为也适用于相反方向。有关映射器的工作原理的更多详细信息,请查看此处

类似地,可以将映射到对象列表

class B { }

class C {

  /** 
   * @Slumber\AsList(
   *   @Slumber\AsObject(B::Class)
   * )
   */
  private $val = [];
}

Slumber\AsMap()

从和到键值对(索引数组)映射值。

注解期望嵌套注解来控制集合内元素的形状。

class C {
  /**
   * @Slumber\AsMap(
   *   @Slumber\AsDecimal()
   * )
   */
  private $val = [1.1, 2.2, 3.3];
}

映射到

{
  "val": { "0": 1.1, "1": 2.2, "2": 3.3 }
}
class C {
  /**
   * @Slumber\AsList(
   *   @Slumber\AsDecimal()
   * )
   */
  private $val = ["a": 1.1, "b": 2.2, "c": 3.3];
}

映射到

{
  "val": { "a": 1.1, "b": 2.2, "c": 3.3}
}

相同的行为也适用于相反方向。有关映射器的工作原理的更多详细信息,请查看此处

类似地,可以将映射到对象列表

class B { }

class C {

  /** 
   * @Slumber\AsMap(
   *   @Slumber\AsObject(B::Class)
   * )
   */
  private $val = [];
}

Slumber\AsKeyValuePairs()

从和到特殊形状的键值对映射值。这在数据库索引方面可能很有用。

注解期望嵌套注解来控制集合内元素的形状。

class C {
  /**
   * @Slumber\AsMap(
   *   @Slumber\AsDecimal()
   * )
   */
  private $val = [1.1, 2.2, 3.3];
}

映射到

{
  "val": [
    { "k": "0", "v": 1.1 }, 
    { "k": "1", "v": 2.2 }, 
    { "k": "2", "v": 3.3 }
  ]
}
class C {
  /**
   * @Slumber\AsList(
   *   @Slumber\AsDecimal()
   * )
   */
  private $val = ["a": 1.1, "b": 2.2, "c": 3.3];
}

映射到

{
  "val": [
    { "k": "a", "v": 1.1 }, 
    { "k": "b", "v": 2.2 }, 
    { "k": "c", "v": 3.3 }
  ]
}

相同的行为也适用于相反方向。有关映射器的工作原理的更多详细信息,请查看此处

类似地,可以将映射到对象列表

class B { }

class C {

  /** 
   * @Slumber\AsKeyValuePairs(
   *   @Slumber\AsObject(B::Class)
   * )
   */
  private $val = [];
}

多态示例

在序列化时不需要多态信息。因为我们知道我们手中确切的类将被序列化。

但在反序列化时,必须显式注释多态。只有通过这样做,我们才能知道要实例化的类。我们还需要在数据中有一个字段,该字段充当判别器。

use PeekAndPoke\Component\Slumber\Annotation\Slumber;

/*
 * @Slumber\Polymorphic(
 *     {
 *         "adyen"  : Adyen::class,
 *         "paypal" : Paypal::class,
 *         "stripe" : Stripe::class,
 *     },
 *     tellBy  = "provider",
 *     default = PaymentMean::class
 * )
 */
class PaymentMean {

  /**
   * The discriminator field
   *
   * @Slumber\AsString()
   */
  private $provider;

  /* ... */
}

class Adyen extends PaymentMean {

  /* ... */
}

class Paypal extends PaymentMean {

  /* ... */
}

class Stripe extends PaymentMean {

  /* ... */
}

票据

下一个票据编号:14

优先级 I

SLUMBER-13 - 0%
( ) 单元测试用于多态性回退到默认
( ) a) 判别器未设置
( ) b) 设置了未知判别器

SLUMBER-12 - 50% - 实现存储在单个集合中的多个类型时的别名类 -> 为了在单个集合中存储多个类型,我们必须能够指定存储库的别名类 (x) 报告于 2016-11-15 (x) 实现 2016-11-15 ( ) 单元测试

SLUMBER-4 - 0% - 将 MongoDbCodec 中的硬编码访问者重构为来自 MongoDbEntityConfig -> 配置读取器必须自动添加访问者 (用户能否以某种方式覆盖这些?) -> 这更通用,并且与用户附加的监听器配合使用时将正常工作 (x) 报告于 2016-05-01
(x) 报告于 2016-05-01

SLUMBER-7 - 0% -

优先级 II

SLUMBER-3 - 0% - 允许 onPreCreate() 等访问者传递事件类而不是多个参数 -> 更好的可扩展性 -> 事件传播可以停止 (x) 报告于 2016-05-01

SLUMBER-2 - 0% - 首先设置和通过获取器和设置器读取属性。如果不可能,则使用反射
-> 读取和写入继承的私有属性将变得可能
-> +33% 速度
(x) 报告于 2016-05-01

SLUMBER-8 - 0% - 为 Data\MongoDB 实现GeoJSON支持
-> 实现 GeoSpatialIndex 以支持 GeoJson 类型 -> 实现 GeoJsonPolygon、GeoJsonMultiPolygon 和其他 GeoJson 类型 (x) 报告于 2016-05-12

SLUMBER-7 - IRepository::save 应该返回比 @return array|null 更具体的结果 (x) 报告于 2016-05-12

优先级 III

SLUMBER-6 - 0% - 将 Slumber\Swagger 建立为自己的包,并基于通用代码生成组件 -> 这是一个自己的项目 -> 移除 gossi/php-code-gen (x) 报告于 2016-05-01

已完成

SLUMBER-1 - 100% - 删除 @AsOne2One 注解,并像 @AsId 一样执行类似操作 -> 当前标记为这样的实体不能与 ArrayCodec 一起使用(这是有问题的行为) (x) 完成 2016-05-11

SLUMBER-5 - 100% - 将 Slumber\MongoDb 移动到 Slumber\Data\MongoDb -> Slumber\Data 将是所有数据库事物的家 (x) 完成 2016-05-11

SLUMBER-9 - 100% - 实现多态的休眠和唤醒 (x) 报告于 2016-05-14 (x) 完成 2016-10-01 (x) 单元测试

SLUMBER-10 - 100% 实现所有 AsCollection 映射的集合类的使用 -> 这将使将传入的数组包装到集合类中成为可能。 -> 这将增加对数组操作的可方便性,因为代码将与数据封装在一起 -> 示例:包含标签的 TagsSet 集合类型可以具有 has()、addUnique()、remove() 等方法 (x) 报告于 2016-11-01 (x) 完成 2016-11-13 (x) 单元测试

SLUMBER-11 - 100%实现了LazyDbRefCollection以存储引用对象的列表(x)报告日期2016-11-13(x)完成日期2016-11-13(x)单元测试