diff --git a/README.md b/README.md
index 5bd5d447..caf186a1 100644
--- a/README.md
+++ b/README.md
@@ -36,13 +36,33 @@
# Laravel Symfony Serializer
-## π About
-
This package integrates the Symfony Serializer component into Laravel, providing a powerful tool for serializing and deserializing objects into various formats such as JSON, XML, CSV, and YAML.
Detailed documentation on the Symfony serializer can be found on their [official page](https://symfony.com/doc/current/components/serializer.html).
-### β Purpose
+
+
+## ποΈ Table of Contents
+
+- [Purpose](#-purpose)
+- [Installation](#-installation)
+- [Configuration](#-configuration)
+ - [Configuration Options](#-configuration-options)
+ - [Custom Strategies](#-custom-strategies)
+- [Usage](#-usage)
+ - [Components](#-components)
+ - [Example DTO](#-example-dto)
+ - [Using `SerializerManager` in your Service Classes](#-using-serializermanager-in-your-service-classes)
+ - [Using `ResponseFactory` in Laravel Controllers](#-using-responsefactory-in-laravel-controllers)
+ - [Using in Laravel Queues](#-using-in-laravel-queues)
+- [Security Policy](#-security-policy)
+- [Want to Contribute?](#-want-to-contribute)
+- [Contributors](#-contributors)
+- [Social Links](#-social-links)
+- [License](#-license)
+- [Credits and Useful Resources](#-credits-and-useful-resources)
+
+## π€ Purpose
This package brings the power of the Symfony Serializer component to Laravel. While Laravel does not have a built-in serializer and typically relies on array or JSON transformations, this package provides more advanced serialization capabilities. This includes object normalization, handling of circular references, property grouping, and format-specific encoders.
@@ -72,27 +92,191 @@ $ php artisan vendor:publish \
+## π§ Configuration
+
+The package configuration file allows you to customize various aspects of the serialization process.
+
+Below is the default configuration provided by the package:
+
+```php
+,
+ * encoderRegistrationStrategy: class-string,
+ * metadataLoader: class-string|null,
+ * }
+ */
+return [
+ 'default' => env('SERIALIZER_DEFAULT_FORMAT', 'symfony-json'),
+
+ 'debug' => env('SERIALIZER_DEBUG_MODE', env('APP_DEBUG', false)),
+
+ 'normalizerRegistrationStrategy' => DefaultNormalizerRegistrationStrategy::class,
+
+ 'encoderRegistrationStrategy' => DefaultEncoderRegistrationStrategy::class,
+
+ 'metadataLoader' => null,
+];
+```
+
+### β Configuration Options
+
+- **`default`**: Specifies the default serializer format. This can be overridden by setting the `SERIALIZER_DEFAULT_FORMAT`environment variable. The default is `symfony-json`.
+- **`debug`**: Enables debug mode for `ProblemNormalizer`. This can be set using the `SERIALIZER_DEBUG_MODE` environment variable. It defaults to the `APP_DEBUG` value.
+- **`normalizerRegistrationStrategy`**: Specifies the strategy class for registering normalizers. The default strategy is [`WayOfDev\Serializer\DefaultNormalizerRegistrationStrategy`](https://github.com/wayofdev/laravel-symfony-serializer/blob/master/src/DefaultNormalizerRegistrationStrategy.php).
+- **`encoderRegistrationStrategy`**: Specifies the strategy class for registering encoders. The default strategy is [`WayOfDev\Serializer\DefaultEncoderRegistrationStrategy`](https://github.com/wayofdev/laravel-symfony-serializer/blob/master/src/DefaultEncoderRegistrationStrategy.php).
+- **`metadataLoader`**: Allows registration of a custom metadata loader. By default, `Symfony\Component\Serializer\Mapping\Loader\AttributeLoader` is used.
+
+### β Custom Strategies
+
+[Due to Laravel's caching limitations, where configs cannot instantiate objects](https://elliotderhay.com/blog/caching-laravel-configs-that-use-objects), this package uses strategies to register normalizers and encoders.
+
+You can create custom normalizer or encoder registration strategies by implementing the respective interfaces.
+
+#### Normalizer Registration Strategy
+
+To create a custom normalizer registration strategy
+
+1. Implement the [`NormalizerRegistrationStrategy`](https://github.com/wayofdev/laravel-symfony-serializer/blob/master/src/Contracts/NormalizerRegistrationStrategy.php) interface:
+
+ ```php
+ }>
+ */
+ public function normalizers(): iterable
+ {
+ // ...
+ }
+ }
+ ```
+
+2. Change `serializer.php` config to use your custom strategy:
+
+ ```php
+ 'normalizerRegistrationStrategy' => CustomNormalizerRegistrationStrategy::class,
+ ```
+
+#### Encoder Registration Strategy
+
+To create a custom encoder registration strategy:
+
+1. Implement the [`EncoderRegistrationStrategy`](https://github.com/wayofdev/laravel-symfony-serializer/blob/master/src/Contracts/EncoderRegistrationStrategy.php) interface:
+
+ ```php
+
+ */
+ public function encoders(): iterable
+ {
+ // Register your encoders here...
+
+ yield ['encoder' => new Encoder\JsonEncoder()];
+ yield ['encoder' => new Encoder\CsvEncoder()];
+ yield ['encoder' => new Encoder\XmlEncoder()];
+
+ if (class_exists(Dumper::class)) {
+ yield ['encoder' => new Encoder\YamlEncoder()];
+ }
+ }
+ }
+ ```
+
+2. Change `serializer.php` config to use your custom strategy:
+
+ ```php
+ 'encoderRegistrationStrategy' => CustomEncoderRegistrationStrategy::class,
+ ```
+
+
+
## π» Usage
The package provides a list of serializers that can be used to serialize and deserialize objects.
-The serializers available in this package are: `symfony-json`, `symfony-csv`, `symfony-xml`, `symfony-yaml`.
+The default serializers available in this package are: `symfony-json`, `symfony-csv`, `symfony-xml`, `symfony-yaml`.
-> **Warning**
+> [!WARNING]
> The `yaml` encoder requires the `symfony/yaml` package and is disabled when the package is not installed.
> Install the `symfony/yaml` package and the encoder will be automatically enabled.
+### β Components
+
+#### SerializerManager
+
+The `SerializerManager` handles the different serializers available in this package. It can be used to serialize and deserialize objects.
+
+#### ResponseFactory
+
+The `ResponseFactory` is used to create responses in Laravel controllers, making it easy to include serialized data in HTTP responses.
+
+#### Facades
+
+This package includes two Laravel Facades:
+
+- `Manager` β To access underlying SerializerManager
+- `Serializer` β To access bound and configured original Symfony Serializer instance.
+
+### β Example DTO
+
We will use this example DTO for serialization purposes:
```php
getSerializer('json');
- $dto = new MyDTO(1, 'John Doe', 'john@example.com');
+ $serializer = $serializer->serializer('symfony-json');
+ $dto = new UserDTO(1, 'John Doe', 'john@example.com');
- $content = $serializer->normalize(
- data: $dto,
+ $serialized = $serializer->serialize(
+ payload: $dto,
context: ['groups' => ['private']]
);
-
- $serialized = $serializer->serialize($content);
}
}
```
-### β Using ResponseFactory in Laravel Controllers
+### β Using `ResponseFactory` in Laravel Controllers
-Here's an example of how you can use the `ResponseFactory` in a Laravel controller:
+Here's an example of how you can use the `ResponseFactory` in a Laravel Controller:
**Example Controller:**
```php
response = $response;
}
public function index()
{
- $dto = new MyDTO(1, 'John Doe', 'john@example.com');
+ $dto = new UserDTO(1, 'John Doe', 'john@example.com');
$this->response->withContext(['groups' => ['private']]);
$this->response->withStatusCode(HttpCode::HTTP_OK);
@@ -201,6 +380,61 @@ class MyController extends Controller
+### β Using in Laravel Queues
+
+To switch from Laravel's default serialization to this implementation in queues, you can override the `__serialize` and `__unserialize` methods in your queue jobs. Hereβs an example:
+
+```php
+product = $product;
+ }
+
+ public function handle(ProductProcessor $processor): void
+ {
+ $processor->process($this->product);
+ }
+
+ public function __serialize(): array
+ {
+ return [
+ 'product' => Manager::serialize($this->product),
+ ];
+ }
+
+ public function __unserialize(array $values): void
+ {
+ $this->product = Manager::deserialize($values['product'], Product::class);
+ }
+}
+```
+
+
+
## π Security Policy
This project has a [security policy](.github/SECURITY.md).
@@ -214,7 +448,7 @@ Thank you for considering contributing to the wayofdev community! We are open to
- π€ [Suggest a feature](https://github.com/wayofdev/laravel-symfony-serializer/issues/new?assignees=&labels=type%3A+enhancement&projects=&template=2-feature-request.yml&title=%5BFeature%5D%3A+)
- π [Report an issue](https://github.com/wayofdev/laravel-symfony-serializer/issues/new?assignees=&labels=type%3A+documentation%2Ctype%3A+maintenance&projects=&template=1-bug-report.yml&title=%5BBug%5D%3A+)
- π [Improve documentation](https://github.com/wayofdev/laravel-symfony-serializer/issues/new?assignees=&labels=type%3A+documentation%2Ctype%3A+maintenance&projects=&template=4-docs-bug-report.yml&title=%5BDocs%5D%3A+)
-- π¨βπ» Contribute to the code
+- π¨βπ» [Contribute to the code](.github/CONTRIBUTING.md)
You are more than welcome. Before contributing, kindly check our [contribution guidelines](.github/CONTRIBUTING.md).
@@ -239,7 +473,7 @@ You are more than welcome. Before contributing, kindly check our [contribution g
-## βοΈ License
+## π License
[![Licence](https://img.shields.io/github/license/wayofdev/laravel-symfony-serializer?style=for-the-badge&color=blue)](./LICENSE.md)
diff --git a/config/serializer.php b/config/serializer.php
index 44512213..37e554f0 100644
--- a/config/serializer.php
+++ b/config/serializer.php
@@ -2,13 +2,19 @@
declare(strict_types=1);
+use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;
+use WayOfDev\Serializer\Contracts\EncoderRegistrationStrategy;
+use WayOfDev\Serializer\Contracts\NormalizerRegistrationStrategy;
+use WayOfDev\Serializer\DefaultEncoderRegistrationStrategy;
+use WayOfDev\Serializer\DefaultNormalizerRegistrationStrategy;
+
/**
* @return array{
* default: string,
* debug: bool,
- * normalizerRegistrationStrategy: class-string,
- * encoderRegistrationStrategy: class-string,
- * metadataLoader: class-string|null,
+ * normalizerRegistrationStrategy: class-string,
+ * encoderRegistrationStrategy: class-string,
+ * metadataLoader: class-string|null,
* }
*/
return [
@@ -38,7 +44,7 @@
* Allows you to specify the strategy class for registering your normalizers.
* Default is 'WayOfDev\Serializer\DefaultNormalizerRegistrationStrategy'.
*/
- 'normalizerRegistrationStrategy' => WayOfDev\Serializer\DefaultNormalizerRegistrationStrategy::class,
+ 'normalizerRegistrationStrategy' => DefaultNormalizerRegistrationStrategy::class,
/*
* Allows you to register your custom encoders.
@@ -53,7 +59,7 @@
* You can replace the default encoders with your custom ones by implementing
* your own registration strategy.
*/
- 'encoderRegistrationStrategy' => WayOfDev\Serializer\DefaultEncoderRegistrationStrategy::class,
+ 'encoderRegistrationStrategy' => DefaultEncoderRegistrationStrategy::class,
/*
* Allows you to register your custom metadata loader.
diff --git a/src/Bridge/Laravel/Facades/Serializer.php b/src/Bridge/Laravel/Facades/Serializer.php
index da11941e..b97f7c9c 100644
--- a/src/Bridge/Laravel/Facades/Serializer.php
+++ b/src/Bridge/Laravel/Facades/Serializer.php
@@ -4,8 +4,26 @@
namespace WayOfDev\Serializer\Bridge\Laravel\Facades;
+use ArrayObject;
use Illuminate\Support\Facades\Facade;
+use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
+use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
+/**
+ * @method static string serialize(mixed $data, string $format, array $context = [])
+ * @method static mixed deserialize(string $data, string $type, string $format, array $context = [])
+ * @method static array|string|int|float|bool|ArrayObject|null normalize(mixed $data, string $format, array $context = [])
+ * @method static mixed denormalize(mixed $data, string $type, ?string $format = null, array $context = [])
+ * @method static array getSupportedTypes(?string $format)
+ * @method static bool supportsNormalization(mixed $data, ?string $format = null, array $context = [])
+ * @method static bool supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = [])
+ * @method static NormalizerInterface|null getNormalizer(mixed $data, ?string $format, array $context)
+ * @method static DenormalizerInterface|null getDenormalizer(mixed $data, string $type, ?string $format, array $context)
+ * @method static string encode(mixed $data, string $format, array $context = [])
+ * @method static mixed decode(string $data, string $type, string $format, array $context = [])
+ * @method static bool supportsEncoding(string $format, array $context = [])
+ * @method static bool supportsDecoding(string $format, array $context = [])
+ */
class Serializer extends Facade
{
protected static function getFacadeAccessor(): string