PHP code example of good-php / serialization

1. Go to this page and download the library: Download good-php/serialization library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

good-php / serialization example snippets


/**
 * @template T1
 */
class Item
{
	/**
	 * @param BackedEnumStub[] $array
	 * @param Collection<int, T1>
	 * @param T1 $generic
	 * @param NestedGeneric<int, T1> $nested
	 */
	public function __construct(
		// Scalars
		public readonly int $int,
		public readonly float $float,
		public readonly string $string,
		public readonly bool $bool,
		// Nullable and optional values
		public readonly ?string $nullableString,
		public readonly int|null|MissingValue $optional,
		// Custom property names
		#[SerializedName('two')] public readonly string $one,
		// Backed enums
		public readonly BackedEnumStub $backedEnum,
		// Generics and nested objects
		public readonly mixed $generic,
		public readonly NestedGenerics $nestedGeneric,
		// Arrays and Illuminate Collection of any type (with generics!)
		public readonly array $array,
		public readonly Collection $collection,
		// Dates
		public readonly DateTime $dateTime,
		public readonly Carbon $carbon,
	) {}
}

$primitiveAdapter = $serializer->adapter(
	PrimitiveTypeAdapter::class, 
	NamedType::wrap(Item::class, [Carbon::class])
);
$primitiveAdapter->serialize(new Item(...)) // -> ['int' => 123, ...]

$jsonAdapter = $serializer->adapter(
	JsonTypeAdapter::class, 
	NamedType::wrap(Item::class, [PrimitiveType::int()])
);
$jsonAdapter->deserialize('{"int": 123, ...}') // -> new Item(123, ...)

final class DateTimeMapper
{
	#[MapTo(PrimitiveTypeAdapter::class)]
	public function serialize(DateTime $value): string
	{
		return $value->format(DateTimeInterface::RFC3339_EXTENDED);
	}

	#[MapFrom(PrimitiveTypeAdapter::class)]
	public function deserialize(string $value): DateTime
	{
		return new DateTime($value);
	}
}

$serializer = (new SerializerBuilder())
	->addMapperLast(new DateTimeMapper())
	->build();

final class ArrayMapper
{
	#[MapTo(PrimitiveTypeAdapter::class)]
	public function to(array $value, Type $type, Serializer $serializer): array
	{
		$itemAdapter = $serializer->adapter(PrimitiveTypeAdapter::class, $type->arguments[1]);
		
		return array_map(fn ($item) => $itemAdapter->serialize($item), $value);
	}

	#[MapFrom(PrimitiveTypeAdapter::class)]
	public function from(array $value, Type $type, Serializer $serializer): array
	{
		$itemAdapter = $serializer->adapter(PrimitiveTypeAdapter::class, $type->arguments[1]);

		return array_map(fn ($item) => $itemAdapter->deserialize($item), $value);
	}
}

final class BackedEnumMapper
{
	#[MapTo(PrimitiveTypeAdapter::class, new BaseTypeAcceptedByAcceptanceStrategy(BackedEnum::class))]
	public function to(BackedEnum $value): string|int
	{
		return $value->value;
	}
	
	#[MapFrom(PrimitiveTypeAdapter::class, new BaseTypeAcceptedByAcceptanceStrategy(BackedEnum::class))]
	public function from(string|int $value, Type $type): BackedEnum
	{
		$enumClass = $type->name;
		
		return $enumClass::tryFrom($value);
	}
}

(new SerializerBuilder())
	->addMapperLast(new TestMapper()) // then this one
	->addFactoryLast(new TestFactory()) // and this one last
	->addFactory(new TestFactory()) // attempted first

public function create(string $typeAdapterType, Type $type, Attributes $attributes, Serializer $serializer): ?TypeAdapter

class NullableTypeAdapterFactory implements TypeAdapterFactory
{
	public function create(string $typeAdapterType, Type $type, Attributes $attributes, Serializer $serializer): ?TypeAdapter
	{
		if ($typeAdapterType !== PrimitiveTypeAdapter::class || !$type instanceof NullableType) {
			return null;
		}

		return new NullableTypeAdapter(
			$serializer->adapter($typeAdapterType, $type->innerType, $attributes),
		);
	}
}

class NullableTypeAdapter implements PrimitiveTypeAdapter
{
	public function __construct(
		private readonly PrimitiveTypeAdapter $delegate,
	) {
	}

	public function serialize(mixed $value): mixed
	{
		if ($value === null) {
			return null;
		}

		return $this->delegate->serialize($value);
	}

	public function deserialize(mixed $value): mixed
	{
		if ($value === null) {
			return null;
		}

		return $this->delegate->deserialize($value);
	}
}

(new SerializerBuilder())->namingStrategy(BuiltInNamingStrategy::SNAKE_CASE);

// Uses snake_case by default
class Item1 {
	public function __construct(
		public int $keyName, // appears as "key_name" in serialized data
		#[SerializedName('second_key')] public int $firstKey, // second_key
		#[SerializedName(BuiltInNamingStrategy::PASCAL_CASE)] public int $thirdKey, // THIRD_KEY
	) {}
}

// Uses PASCAL_CASE by default
#[SerializedName(BuiltInNamingStrategy::PASCAL_CASE)]
class Item2 {
	public function __construct(
		public int $keyName, // KEY_NAME
	) {}
}

class PrefixedNaming implements NamingStrategy {
	public function __construct(
		private readonly string $prefix,
	) {}
	
	public function translate(PropertyReflection $property): string
	{
		return $this->prefix . $property->name();
	}
}

#[SerializedName(new PrefixedNaming('$'))]
class SiftTrackData {}

class Item {
	public function __construct(
		public ?int $first, // set to null
		public bool $second = true, // set to true
		public Item $third = new Item(...), // set to Item instance
		public int|MissingValue $fourth, // set to MissingValue::INSTANCE
		public int $fifth, // ond' => false, ...]);

class Pagination {
	public function __construct(
		public readonly int $perPage,
		public readonly int $total,
	) {}
}

class UsersPaginatedList {
	public function __construct(
		#[Flatten]
		public readonly Pagination $pagination,
		/** @var User[] */
		public readonly array $users,
	) {}
}

// {"perPage": 25, "total": 100, "users": []}
$adapter->serialize(
	new UsersPaginatedList(
		pagination: new Pagination(25, 100),
		users: [],
	)
);

interface XmlTypeAdapter extends TypeAdapter {}

final class FromPrimitiveXmlTypeAdapter implements XmlTypeAdapter
{
	public function __construct(
		private readonly PrimitiveTypeAdapter $primitiveAdapter,
	) {
	}

	public function serialize(mixed $value): mixed
	{
		return xml_encode($this->primitiveAdapter->serialize($value));
	}

	public function deserialize(mixed $value): mixed
	{
		return $this->primitiveAdapter->deserialize(xml_decode($value));
	}
}