42sol/json-decoder

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

dev-master 2024-07-25 12:52 UTC

This package is auto-updated.

Last update: 2024-09-25 13:09:27 UTC


README

    Packagist Downloads

PHP的JsonDecoder

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

安装

您可以通过composer安装此包

composer require karriere/json-decoder

使用方法

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

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

JsonDecoder类可以接收一个名为shouldAutoCase的参数。如果设置为true,它将尝试自动从snake-case或kebab-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:给出完全限定的类名,例如:您的命名空间\类
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映射到类型为$type的类实例,并在$jsonField中包含数据的字段映射。

ArrayBinding

为给定类型定义数组字段绑定。

签名

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

这定义了将属性$property映射到类型为$type的类实例数组,并在$jsonField中包含数据的字段映射。

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获取更多信息。