nstwf / json-mapper
Map json data to objects
0.8.4
2022-06-07 05:56 UTC
Requires
- php: ^8.1
- nstwf/extended-reflection-class: ^1.0
- psr/simple-cache: ^3.0
Requires (Dev)
- phpunit/phpunit: 9.5.16
- vimeo/psalm: ^4.22
README
Library for mapping json data to objects using constructor
Contents
Installation
composer require nstwf/json-mapper
Usage
$factory = new \Nstwf\JsonMapper\JsonMapper\JsonMapperFactory();
$jsonMapper = $factory->create();
$data = (object)[
"id" => "123e4567-e89b-12d3-a456-426614174000",
"roles" => [1, 3, 7],
"profile" => [
"name" => "Alex",
"age" => 19,
]
];
$jsonMapper->mapObject($data, User::class);
Supported types:
- Scalar types (int, float, bool, string, array, mixed)
- Enums
- Classes
- Array of scalar types, enums and classes
- Nullable types
Inspectors
Here describe all supported inspectors. You can customize them, if you do not use some features describe there - to optimize it
Notes:
- To declare array of any type (especially for class and enum) - use phpDoc
- If class in phpDoc does not contain namespace - try to discover namespace from the use statement if it exists
- Constructor parameter must use same name as property
- Union type is chosen by equal comparison with the data type:
- For scalar only: if no one of described types is not suitable - value will be cast to first type
- Union types declare from left to right.
- Be careful: enum with backed type can be mapped as scalar type value, if it uses together in union. Preferred types should come first
Typed properties
$inspector = (new \Nstwf\JsonMapper\Inspector\InspectorBuilder())
->withTypesProperties()
->build();
class Example {
private int $scalar;
private int|string $union;
private ?int $nullable;
private User $class;
}
Property @var
annotations
$inspector = (new \Nstwf\JsonMapper\Inspector\InspectorBuilder())
->withPropertyAnnotations()
->build();
use App\Models\User;
class Example {
/** @var int */
private $scalar;
/** @var int|string */
private $union;
/** @var int[] */
private $array;
/** @var int|null */
private $nullable;
/** @var User */
private $class;
/** @var \App\Models\Role */
private $classWithNamespace;
}
Constructor typed parameters
$inspector = (new \Nstwf\JsonMapper\Inspector\InspectorBuilder())
->withConstructorParameters()
->build();
class Example {
public function __construct(
int $scalar,
int|string $union,
?int $nullable,
User $class
) {
$this->scalar = $scalar;
/** more */
}
}
Constructor @param
annotations
$inspector = (new \Nstwf\JsonMapper\Inspector\InspectorBuilder())
->withConstructorAnnotations()
->build();
use App\Models\User;
class Example {
/**
* @param int $scalar
* @param int|string $union
* @param int[] $array
* @param int|null $nullable
* @param User $class
* @param \App\Models\Role $classWithNamespace
*/
public function __construct(/*parameters*/) {}
}
Property CustomName
attribute
$inspector = (new \Nstwf\JsonMapper\Inspector\InspectorBuilder())
->withCustomNameAttribute()
->build();
class Example {
#[\Nstwf\JsonMapper\Attribute\CustomName('custom_name')]
private $property;
}
Cache
All inspectors can receive cache. Default cache for inspectors - array. You can use self implementation, using: Psr\SimpleCache\CacheInterface
$inspectorBuilder = new \Nstwf\JsonMapper\Inspector\InspectorBuilder();
$inspector = $inspectorBuilder
->withCache($redisCache)
->withTypesProperties()
->withPropertyAnnotations()
->build();
Customize
Use native builders to customize your json mapper for your needs
// Customize inspectors
$inspectorBuilder = new \Nstwf\JsonMapper\Inspector\InspectorBuilder();
$inspector = $inspectorBuilder
->withTypesProperties()
->withPropertyAnnotations()
->build();
// Add own types to registry
$registry = new \Nstwf\JsonMapper\Registry\ClassFactoryRegistry();
$registry->add(Uuid::class, fn(string $value) => new Uuid($value));
// Use object mapper builder
$propertyMapperBuilder = new \Nstwf\JsonMapper\Property\Mapper\PropertyMapperBuilder();
$propertyMapper = $propertyMapperBuilder
->withClassFactoryRegistry($registry)
->build();
$objectMapperBuilder = new \Nstwf\JsonMapper\Object\Mapper\ObjectMapperBuilder();
$objectMapper = $objectMapperBuilder
->withPropertyMapper($propertyMapper)
->build();
// Create JsonMapper
$factory = new \Nstwf\JsonMapper\JsonMapper\JsonMapperFactory();
$jsonMapper = $factory->create($inspector, $objectMapper);
Customize types mapping
You can customize mapping for some classes. For example: json contains uuid as string, but in the object it defined as Uuid class. Just add class with custom mapping
{
"id": "123e4567-e89b-12d3-a456-426614174000"
}
class User {
private Uuid $id;
}
$registry = new \Nstwf\JsonMapper\Registry\ClassFactoryRegistry();
$registry->add(
Uuid::class, fn(string $value) => new Uuid($value)
);
Customize inspectors
You can specify type discover using builder. All available inspectors defined here.
// Example: if you do not use constructors
$builder = new \Nstwf\JsonMapper\Inspector\InspectorBuilder();
$builder->withTypesProperties()
->withPropertyAnnotations()
->build();