karriere/json-decoder

JsonDecoder 实现允许您将 JSON 数据转换为 PHP 类对象

v5.0.0 2023-03-01 09:48 UTC

This package is auto-updated.

Last update: 2024-08-29 13:11:43 UTC


README

    Packagist Downloads

PHP 的 JsonDecoder

此包包含一个 JsonDecoder 实现,允许您将 JSON 数据转换为 php 类对象,而不是 stdclass

安装

您可以通过 composer 安装此包

composer require karriere/json-decoder

使用方法

默认情况下,解码器将遍历所有定义的 JSON 字段,并尝试在给定的类类型实例上设置这些值。这种行为的变化允许在像 Laravel 的 Eloquent 模型这样的使用 魔法 __get__set 函数的类上使用 json-decoder

如果找到与 JSON 字段同名或显式定义了 绑定 的属性,它将解码到定义的位置。否则,属性将仅创建和分配(如果您使用的是 PHP 8.2,则需要 #[AllowDynamicProperties] 属性)。

JsonDecoder 类可以接收一个名为 shouldAutoCase 的参数。如果设置为 true,它将尝试在未注册其他绑定的情况下自动从 snake-case 或 kebap-case 查找 camel-case 版本,并且如果找到其中一个变体,它将使用 AliasBinding

简单示例

假设您有一个类似下面的 Person

#[AllowDynamicProperties]
class Person
{
    public int $id;
    public string $name;
    public ?string $lastname = '';
}

以下代码将转换给定的 JSON 数据到 Person 的一个实例。

$jsonDecoder = new JsonDecoder();
$jsonData = '{"id": 1, "name": "John Doe", "lastname": null, "dynamicProperty": "foo"}';

$person = $jsonDecoder->decode($jsonData, Person::class);

请注意,由于 PHP 8.2 中动态属性已被弃用,因此如果您仍希望使用这些动态属性,您必须在类中添加 PHP 属性 AllowDynamicProperties。如果您使用的是 PHP 8.2(以及更高版本)且未使用 AllowDynamicProperties 属性,则所有动态属性都将被忽略。

更复杂的使用案例

让我们通过一个名为 address 的属性扩展前面的示例。此地址字段应包含 Address 的一个实例。从版本 4 开始,您可以使用引入的 scanAndRegister 方法自动根据类注释生成转换器。从版本 5 开始,您还可以使用属性类型而不是类注释。

class Person
{
    public int $id;
    public string $name;

    /**
     * @var Address
     */
    public $address;
    
    public ?Address $typedAddress = null;
}

对于此类定义,我们可以如下解码 JSON 数据

$jsonDecoder = new JsonDecoder();
$jsonDecoder->scanAndRegister(Person::class);

$jsonData = '{"id": 1, "name": "John Doe", "address": {"street": "Samplestreet", "city": "Samplecity"}, , "typedAddress": {"street": "Samplestreet", "city": "Samplecity"}}';

$person = $jsonDecoder->decode($jsonData, Person::class);

定义转换器

如果您不使用注释或需要更灵活的 Transformer,您还可以创建一个自定义转换器。让我们看看没有注释的先前示例。

class Person
{
    public int $id;
    public string $name;
    public mixed $address;
}

要能够将地址数据转换为 Address 类对象,您需要为 Person 定义一个转换器

转换器接口定义了两个方法

  • register:在这里,您注册您的字段、数组、别名和回调绑定
  • transforms:给出全限定类名,例如:Your\Namespace\Class
class PersonTransformer implements Transformer
{
    public function register(ClassBindings $classBindings)
    {
        $classBindings->register(new FieldBinding('address', 'address', Address::class));
    }

    public function transforms()
    {
        return Person::class;
    }
}

注册转换器后,JsonDecoder 将使用定义的转换器

$jsonDecoder = new JsonDecoder();
$jsonDecoder->register(new PersonTransformer());

$jsonData = '{"id": 1, "name": "John Doe"}';

$person = $jsonDecoder->decode($jsonData, Person::class);

处理私有和受保护属性

从版本4开始,JsonDecoder类将自动处理privateprotected属性。

元素数组的转换

如果你的JSON在根级别包含元素数组,你可以使用decodeMultiple方法将JSON数据转换为类的对象数组。

$jsonDecoder = new JsonDecoder();

$jsonData = '[{"id": 1, "name": "John Doe"}, {"id": 2, "name": "Jane Doe"}]';

$personArray = $jsonDecoder->decodeMultiple($jsonData, Person::class);

文档

转换绑定

以下Binding实现可用:

FieldBinding

为给定类型定义JSON字段到属性的绑定。

签名

new FieldBinding(string $property, ?string $jsonField = null, ?string $type = null, bool $isRequired = false);

这定义了属性$property到具有$jsonField数据的类实例$type的字段映射。

ArrayBinding

定义了给定类型的数组字段绑定。

签名

new ArrayBinding(string $property, ?string $jsonField = null, ?string $type = null, bool $isRequired = false);

这定义了属性$property到具有$jsonField数据的类实例类型$type的数组字段映射。

AliasBinding

定义了JSON字段到属性绑定。

签名

new AliasBinding(string $property, ?string $jsonField = null, bool $isRequired = false);

DateTimeBinding

定义了JSON字段到属性绑定,并将给定的字符串转换为DateTime实例。

签名

new DateTimeBinding(string $property, ?string $jsonField = null, bool $isRequired = false, $dateTimeFormat = DateTime::ATOM);

CallbackBinding

定义了一个属性绑定,它将回调结果集作为其值。

签名

new CallbackBinding(string $property, private Closure $callback);

许可

Apache License 2.0 请参阅LICENSE获取更多信息。