anujrnair/php-json-marshaller

一个用于将 JSON 字符串序列化和反序列化到填充 PHP 类的库

v1.0.1 2016-12-12 18:12 UTC

This package is auto-updated.

Last update: 2024-09-29 03:36:34 UTC


README

一个通过注解驱动的库,用于将 JSON 字符串序列化和反序列化到填充 PHP 类

我们希望对序列化和反序列化有更细粒度的控制,因为

  • json_decode 总是返回一个 StdClass 对象。我们希望能够将解码结果放入我们的自定义类中。
  • 我们可以添加我们接收/发送的数据的预期类型信息,并在使用之前进行验证。
  • json_encode 无法按属性逐个控制。这将允许我们做到这一点。

最新版本可在此处找到: https://github.com/AnujRNair/php-json-marshaller

安装

$ git clone https://github.com/AnujRNair/php-json-marshaller.git
$ composer install

使用

在您的类中,为您的属性和方法添加 MarshallProperty 注解,以描述 JSON 应该如何序列化或反序列化。

MarshallProperty 注解需要一个名称和类型,否则将抛出异常。

您可以在任何公共属性或方法上执行此操作。

use PhpJsonMarshaller\Annotations\MarshallProperty;

class User
{

    /**
     * @MarshallProperty(name="id", type="int")
     * This property is public - it will be accessed directly
     */
    public $id;
    
    /**
    * This property is NOT public - it must be accessed through a getter (marshalling) or a setter (unmarshalling)
    */
    protected $name;
    
    /**
     * @MarshallProperty(name="name", type="string")
     * This function will be used for marshalling json
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @MarshallProperty(name="name", type="string")
     * This function will be used for unmarshalling json
     */
    public function setName($name)
    {
        $this->name = $name;
    }
    
}

配置您的类后,加载 JSONMarshaller 类的一个实例,并调用 marshall 或 unmarshall 函数

use PhpJsonMarshaller\Decoder\ClassDecoder;
use PhpJsonMarshaller\Marshaller\JsonMarshaller;
use PhpJsonMarshaller\Reader\DoctrineAnnotationReader;

$json = '{
    "id": 12345,
    "name": "Anuj"
}';

// Assuming autoloading
$marshaller = new JsonMarshaller(new ClassDecoder(new DoctrineAnnotationReader()));

// Notice the fully qualified namespace!
$user = $marshaller->unmarshall($json, '\My\Example\User');

// Use the new class
echo $user->getName(); // (string) 'Anuj'

// Marshall the class
$marshalled = $marshaller->marshall($user);

// $json and $marshalled are both json_encoded string holding the same data
$json == $marshalled;

现在 $user 变量应该是 \My\Example\User 类的实例,并用我们从 JSON 字符串中传递的 id 和 name 填充。

$marshalled 变量将是一个包含 \My\Example\User 对象实例数据的 json 编码字符串。

嵌套对象

您还可以在类内部嵌套类,以进行递归序列化和反序列化,如下所示

use PhpJsonMarshaller\Annotations\MarshallProperty;

class User
{

    /**
     * @MarshallProperty(name="address", type="\My\Example\Address")
     * Notice the fully qualified namespace!
     */
    public $address;

}

然后在您的代码中

use PhpJsonMarshaller\Decoder\ClassDecoder;
use PhpJsonMarshaller\Marshaller\JsonMarshaller;
use PhpJsonMarshaller\Reader\DoctrineAnnotationReader;

$json = '{
    "id": 12345,
    "name": "Anuj",
    "address": {
        "id": 1,
        "street": "123 Main Street"
    }
}';

// Assuming autoloading
$marshaller = new JsonMarshaller(new ClassDecoder(new DoctrineAnnotationReader()));

// Notice the fully qualified namespace!
$user = $marshaller->unmarshall($json, '\My\Example\User');

// Use the nested object
$user->getAddress()->getStreet(); // (string) "123 Main Street"

对象数组

您可以通过在 MarshallProperty 注解的类型中指示来序列化和反序列化标量/对象的数组

use PhpJsonMarshaller\Annotations\MarshallProperty;

class User
{

    /**
     * @MarshallProperty(name="flags", type="\My\Example\Flag[]")
     * Notice the fully qualified namespace and the array indicator in the type
     */
    public $flags;

}

然后在您的代码中

use PhpJsonMarshaller\Decoder\ClassDecoder;
use PhpJsonMarshaller\Marshaller\JsonMarshaller;
use PhpJsonMarshaller\Reader\DoctrineAnnotationReader;

$json = '{
    "id": 12345,
    "name": "Anuj",
    "flags": [
        {
            "id": 11087,
            "value": 0
        },
        {
            "id": 11088,
            "value": 1
        }
    ],
}';

// Assuming autoloading
$marshaller = new JsonMarshaller(new ClassDecoder(new DoctrineAnnotationReader()));

// Notice the fully qualified namespace!
$user = $marshaller->unmarshall($json, '\My\Example\User');

// Use the data
$user->getFlags()[0]->getId(); // (int) 11087

使用构造函数反序列化对象

要使用具有必需参数的构造函数反序列化对象,请使用 @MarshallCreator 注解来告诉序列化器使用哪些值来实例化类。

此注解接受一个 @MarshallProperty 对象数组,如下所示

use PhpJsonMarshaller\Annotations\MarshallCreator;
use PhpJsonMarshaller\Annotations\MarshallProperty;

class User
{

    /**
     * @var int $id
     */
    protected $id;

    /**
     * @var float $rank
     */
    protected $rank;

    /**
     * @MarshallCreator({@MarshallProperty(name="id", type="int"), @MarshallProperty(name="rank", type="float")})
     */
    public function __construct($id, $rank)
    {
        $this->id = $id;
        $this->rank = $rank;
    }

}

序列化器将在传递给它的 json 字符串中查找这些值(与类实例化的同一级别)并使用这些值实例化对象。

缓存

您可以通过缓存解码类来提高性能。这 不会 缓存来自 JSON 字符串的数据。

为此,实例化一个 Cache 类的实例,并传入一个存储类型。然后将其传递给 ClassDecoder 实例

use PhpJsonMarshaller\Cache\Cache;
use PhpJsonMarshaller\Cache\Storage\InMemoryStorage;
use PhpJsonMarshaller\Decoder\ClassDecoder;
use PhpJsonMarshaller\Marshaller\JsonMarshaller;
use PhpJsonMarshaller\Reader\DoctrineAnnotationReader;

$marshaller = new JsonMarshaller(
    new ClassDecoder(
        new DoctrineAnnotationReader(),
        new Cache(
            new InMemoryStorage()
        )
    )
);

请参阅 \PhpJsonMarshaller\Cache\Storage 以获取所有可用的存储类型。MemcachedStorage 也有一些您可以设置的选项。

未知条目

您可以通过添加 MarshallConfig 注解到特定的类来专门允许一个类在遇到任何未知 JSON 变量时失败

use PhpJsonMarshaller\Annotations\MarshallConfig;

/**
 * @MarshallConfig(ignoreUnknown=false)
 */
class User
{

}

现在如果您尝试将一个未知变量反序列化到这个类中,将会抛出异常。

测试

测试由 PHPUnit 覆盖。浏览到库的根目录并运行 phpunit

请确保 memcached 守护进程正在运行以确保 MemcachedStorageTest 测试通过。

许可

请参阅 许可