Installation Add the package via Composer:
composer require api-platform/serializer
Register the ApiPlatform\Serializer\Serializer\SerializerItemNormalizer in your Laravel service provider (e.g., AppServiceProvider):
use ApiPlatform\Serializer\Serializer\SerializerItemNormalizer;
public function register()
{
$this->app->bind(SerializerItemNormalizer::class, function ($app) {
return new SerializerItemNormalizer(
$app->make('serializer.normalizer.context_builder'),
$app->make('serializer.property_accessor'),
$app->make('serializer.property_info_extractor'),
$app->make('serializer.naming_strategy'),
$app->make('serializer.object_to_populate_extractor'),
$app->make('serializer.object_to_populate_validator'),
$app->make('serializer.name_converter')
);
});
}
First Use Case Serialize a Laravel Eloquent model to JSON:
use ApiPlatform\Serializer\Serializer\SerializerInterface;
$serializer = app(SerializerInterface::class);
$data = $serializer->serialize(new User(), 'json');
// Output: {"id":1,"name":"John Doe","email":"john@example.com"}
Where to Look First
SerializerItemNormalizer and Serializer classes in src/Serializer/.vendor/api-platform/serializer/src/Serializer/ for core logic and vendor/api-platform/core (if installed) for Laravel-specific extensions.Basic Serialization Serialize Eloquent models, collections, or arrays:
$serializer = app(SerializerInterface::class);
$user = User::find(1);
$serialized = $serializer->serialize($user, 'json');
Deserialization Convert JSON back to PHP objects/arrays:
$data = '{"name":"Jane","email":"jane@example.com"}';
$deserialized = $serializer->deserialize($data, User::class, 'json');
Context Customization Pass context to control serialization (e.g., groups, ignore nulls):
$context = [
'groups' => ['public'],
'ignore_null_values' => true,
];
$serializer->serialize($user, 'json', $context);
Normalizer Chaining Extend or replace normalizers (e.g., for custom types):
$normalizers = [
new \ApiPlatform\Serializer\Normalizer\DateTimeNormalizer(),
new \ApiPlatform\Serializer\Normalizer\ObjectNormalizer(),
new \YourApp\CustomNormalizer(),
];
$serializer = new Serializer($normalizers, []);
Laravel-Specific Integration
App\Http\Middleware\TransformsResponse or controllers:
return response()->json($serializer->serialize($data, 'json'));
$validated = $serializer->deserialize($request->getContent(), StoreUserDto::class, 'json');
Dynamic Metadata
Use ApiPlatform\Metadata\Operation or ApiPlatform\Metadata\Property for runtime serialization rules (if paired with api-platform/core).
Leverage Laravel’s Service Container
Bind the serializer as a singleton in AppServiceProvider for reuse:
$this->app->singleton(SerializerInterface::class, function ($app) {
return new Serializer($app->make('serializer.normalizers'), []);
});
Compose with Laravel’s HTTP Layer
Integrate with Illuminate\Http\Request and Illuminate\Http\Response:
$request->getContent(); // Deserialize
response()->json($serializer->serialize($data)); // Serialize
Use with Laravel Collections Serialize collections efficiently:
$users = User::all();
$serialized = $serializer->serialize($users->toArray(), 'json');
Custom Naming Strategies Override default naming (e.g., snake_case to camelCase):
use ApiPlatform\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
$serializer = new Serializer($normalizers, [], $nameConverter);
Event-Driven Extensions
Listen to serializer.normalize events (if using Laravel Events) to modify output dynamically.
Circular References
User hasMany Post, Post belongsTo User) throws Maximum function nesting level errors.max_depth in context or implement a custom normalizer:
$context = ['max_depth' => 2];
Type Mismatches
string vs int).ApiPlatform\Serializer\Normalizer\ObjectNormalizer with strict type checking or validate input first.Laravel-Specific Quirks
ApiPlatform\Serializer\Normalizer\DateTimeNormalizer for dates.Performance Overhead
groups or attributes.Context Overrides
groups) may not propagate as expected in nested objects.context_builder to merge or override contexts dynamically.Enable Verbose Output Inspect normalizer calls by adding debug logging:
$serializer->serialize($data, 'json', ['debug' => true]);
Check Normalizer Order Ensure custom normalizers run after default ones (order matters):
$normalizers = [
new \ApiPlatform\Serializer\Normalizer\ObjectNormalizer(),
new \YourApp\CustomNormalizer(), // Runs after ObjectNormalizer
];
Validate Deserialization
Use ApiPlatform\Serializer\Validator\ValidatorInterface to catch deserialization errors early:
$validator = app(ValidatorInterface::class);
$validator->validate($deserializedData, $context);
Inspect Metadata Dump metadata for complex objects:
$propertyInfoExtractor = app('serializer.property_info_extractor');
$metadata = $propertyInfoExtractor->getMetadataForClass(User::class);
dd($metadata);
Custom Normalizers
Create a normalizer for unsupported types (e.g., Carbon\Carbon):
use ApiPlatform\Serializer\Normalizer\NormalizerInterface;
class CarbonNormalizer implements NormalizerInterface
{
public function normalize($object, string $format = null, array $context = [])
{
return $object->format(\DateTime::ATOM);
}
// ... other required methods
}
Context Builders Dynamically build context based on request:
use ApiPlatform\Serializer\Serializer\SerializerContextBuilderInterface;
class LaravelContextBuilder implements SerializerContextBuilderInterface
{
public function createFromRequest(Request $request): array
{
return [
'groups' => $request->query('groups', []),
'locale' => app()->getLocale(),
];
}
}
Name Converters Modify property naming (e.g., for API versioning):
use ApiPlatform\Serializer\NameConverter\NameConverterInterface;
class VersionedNameConverter implements NameConverterInterface
{
public function convertName(string $propertyName): string
{
return 'v1_'.$propertyName;
}
}
Property Accessors Override property access for private/protected fields:
use ApiPlatform\Serializer\PropertyAccessor\PropertyAccessorInterface;
class LaravelPropertyAccessor implements PropertyAccessorInterface
{
public function getValue(object $object, string $property): mixed
{
return $object->{$
How can I help you explore Laravel packages today?