Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Serializer Laravel Package

jms/serializer

Serialize and deserialize complex PHP object graphs to JSON or XML with flexible metadata (annotations, YAML, XML). Handles circular references, exclusion strategies, versioning, dates/intervals, and integrates with Doctrine ORM—ideal for APIs and data interchange.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup in Laravel
1. **Installation**:
   ```bash
   composer require jms/serializer-bundle

For Laravel, use the standalone package (no bundle required):

composer require jms/serializer
  1. Basic Serialization:

    use JMS\Serializer\SerializerBuilder;
    
    $serializer = SerializerBuilder::create()->build();
    $data = ['name' => 'John', 'age' => 30];
    $json = $serializer->serialize($data, 'json');
    
  2. First Use Case: Convert a Laravel Eloquent model to JSON with custom formatting:

    $user = User::find(1);
    $json = $serializer->serialize($user, 'json', [
        'groups' => ['user:minimal'] // Use serialization groups
    ]);
    
  3. Where to Look First:

    • Official Documentation (especially the "Quick Start" and "Annotations" sections).
    • src/JMS/Serializer/ for core classes (e.g., SerializerBuilder, SerializationContext).
    • Laravel-specific examples in the GitHub issues.

Implementation Patterns

Core Workflows

  1. Serialization Groups: Use annotations or YAML/XML configs to define groups (e.g., user:minimal, user:detailed) and control output granularity.

    // In your model (using annotations)
    /**
     * @JMS\Expose(groups={"user:minimal"})
     */
    private $name;
    
    // In code
    $serializer->serialize($user, 'json', ['groups' => ['user:minimal']]);
    
  2. Handling Eloquent Models:

    • Doctrine Integration: Enable Doctrine metadata driver:
      $builder = SerializerBuilder::create()
          ->configureMetadataDriver(
              new JMS\Serializer\Metadata\Driver\DoctrineAnnotationDriver(
                  new JMS\Serializer\Metadata\Driver\AnnotationDriver(
                      new JMS\Serializer\Metadata\Annotation\AnnotationReader()
                  ),
                  new Doctrine\Common\Annotations\AnnotationReader()
              )
          );
      
    • Custom Handlers: Override default behavior for DateTime, Collection, etc.:
      $builder->addHandler('datetime', new CustomDateHandler());
      
  3. API Responses: Normalize API responses with consistent formatting:

    $response = [
        'data' => $serializer->serialize($user, 'json', ['groups' => ['user:minimal']]),
        'meta' => ['count' => 1]
    ];
    return response()->json($response);
    
  4. Deserialization: Convert JSON/XML back to objects (e.g., for API requests):

    $data = $serializer->deserialize($json, 'App\Models\User', 'json');
    

Integration Tips

  • Laravel Service Provider: Bind the serializer to the container for dependency injection:

    public function register()
    {
        $this->app->singleton('serializer', function () {
            return SerializerBuilder::create()->build();
        });
    }
    

    Then inject via constructor:

    public function __construct(private SerializerInterface $serializer) {}
    
  • Middleware for API Responses: Use middleware to auto-serialize Eloquent models in JSON responses:

    public function handle($request, Closure $next)
    {
        $response = $next($request);
        if ($response->getContent() instanceof \Illuminate\Database\Eloquent\Model) {
            $response->setContent(
                $this->serializer->serialize($response->getContent(), 'json')
            );
        }
        return $response;
    }
    
  • Form Request Validation: Deserialize incoming JSON payloads:

    public function rules()
    {
        $data = $this->serializer->deserialize(
            $this->input('data'),
            'array',
            'json'
        );
        return [
            'data.name' => 'required|string',
            // ...
        ];
    }
    

Gotchas and Tips

Pitfalls

  1. Circular References:

    • Default behavior throws an exception. Use max_depth in context to limit recursion:
      $serializer->serialize($object, 'json', [
          'max_depth' => 5
      ]);
      
    • For nested relationships, use @MaxDepth annotation or custom handlers.
  2. Doctrine Proxy Objects:

    • Serializing Doctrine proxies may cause issues. Use @ExclusionPolicy or disable proxy handling:
      $builder->configureHandlers(function (HandlerRegistry $registry) {
          $registry->getSubscribingHandlerInterface('JMS\Serializer\Handler\ProxyHandler')->setProxyInterface(
              Doctrine\ORM\PersistentCollection::class
          );
      });
      
  3. Type Mismatches:

    • Deserializing to strict types (e.g., DateTimeImmutable) may fail. Use custom handlers or configure the builder:
      $builder->addHandler('DateTimeImmutable', new DateTimeHandler());
      
  4. Annotation Caching:

    • Clear cache when adding/removing annotations:
      php artisan cache:clear
      
    • For development, disable caching:
      $builder->configureMetadataDriver(new AnnotationDriver(
          new AnnotationReader(),
          null, // Disable cache
          false
      ));
      
  5. XML Namespaces:

    • XML serialization may require explicit namespace handling:
      $serializer->serialize($object, 'xml', [
          'xml_root_node_name' => 'root',
          'xml_format_output' => true,
          'xml_root_attributes' => ['xmlns' => 'http://example.com']
      ]);
      

Debugging Tips

  1. Enable Verbose Output:

    $serializer->serialize($object, 'json', [
        'debug' => true
    ]);
    

    Logs metadata and context during serialization.

  2. Check Metadata: Inspect generated metadata for a class:

    $metadata = $serializer->getMetadataFactory()->getMetadataFor(
        'App\Models\User'
    );
    dump($metadata);
    
  3. Handler Debugging: Override handlers to log input/output:

    $builder->addHandler('App\Models\User', new class implements SubscribingHandlerInterface {
        public function getSubscribingMethods()
        {
            return [
                new SubscribingMethod('serializeUser', [], 'json', [
                    new Attribute('groups', ['user:minimal'])
                ])
            ];
        }
    
        public function serializeUser($visitor, User $user, array $type)
        {
            \Log::debug('Serializing user', ['user' => $user->toArray()]);
            return $visitor->visitString($user->name);
        }
    });
    

Extension Points

  1. Custom Handlers: Create handlers for complex types (e.g., Laravel collections, custom value objects):

    $builder->addHandler('Illuminate\Support\Collection', new class implements SubscribingHandlerInterface {
        public function getSubscribingMethods()
        {
            return [
                new SubscribingMethod('serializeCollection', [], 'json', [
                    new Attribute('groups', ['collection'])
                ])
            ];
        }
    
        public function serializeCollection($visitor, Collection $collection, array $type)
        {
            return $visitor->visitArray($collection->toArray());
        }
    });
    
  2. Dynamic Metadata: Use Metadata\ClassMetadataFactory to dynamically add metadata:

    $factory = $serializer->getMetadataFactory();
    $metadata = $factory->getMetadataFor('App\Models\User');
    $metadata->propertyMetadata['email']->setGroups(['user:minimal']);
    
  3. Event Listeners: Attach listeners to serialization events:

    $serializer->getEventDispatcher()->addListener(
        Serializer::EVENT_SERIALIZE_OBJECT_START,
        function (ObjectEvent $event) {
            if ($event->getObject() instanceof User) {
                $event->setData(['custom_field' => 'value']);
            }
        }
    );
    
  4. PHP Attributes (PHP 8+): Use native attributes for metadata (no annotations needed):

    #[JMS\Serializer\Expose(groups: ['user:minimal'])]
    private string $name;
    

    Enable in the builder:

    $builder->enableAttributes();
    

Laravel-Specific Quirks

  1. Eloquent Relationships:

    • Lazy-loaded relationships may cause UndefinedPropertyException. Eager-load or use @MaxDepth:
      /**
       * @JMS\Expose(maxDepth=1)
       */
      public function posts() {}
      
  2. Carbon Instances:

    • Convert Carbon to DateTime before serialization:
      $builder->addHandler('Carbon\Carbon', new class implements SubscribingHandlerInterface
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament