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

Powerful PHP serializer/deserializer for complex object graphs, with JSON/XML support, circular reference handling, rich exclusion strategies, versioning, and built-in type handlers. Configurable via annotations, YAML, or XML; integrates with Doctrine ORM.

View on GitHub
Deep Wiki
Context7
## Getting Started

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

For Laravel, manually register the bundle in config/app.php under extra.bundles:

JMS\SerializerBundle\JMSSerializerBundle::class,
  1. Basic Serialization:

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

    $user = User::find(1);
    $serializer = app('jms_serializer');
    $json = $serializer->serialize($user, 'json', [
        'groups' => ['user:read']
    ]);
    

Key Configuration

  • Annotations: Enable in config/packages/jms_serializer.yaml:
    jms_serializer:
        metadata:
            directories:
                - { path: '%kernel.project_dir%/src/Metadata', namespace_prefix: 'App\Metadata' }
    
  • Handlers: Register custom handlers in config/packages/jms_serializer.yaml:
    jms_serializer:
        handlers:
            custom_date_handler:
                type: App\Serializer\Handler\CustomDateHandler
    

Implementation Patterns

Common Workflows

1. API Response Serialization

  • Group-Based Serialization:
    $serializer->serialize($resource, 'json', [
        'groups' => ['api', 'public']
    ]);
    
  • Dynamic Group Assignment:
    $context = new SerializationContext();
    $context->setGroups(['api']);
    $context->setAttribute('version', 'v1');
    $serializer->serialize($data, 'json', $context);
    

2. Deserialization (e.g., API Requests)

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

3. Doctrine Integration

  • Embeddables:
    // In metadata (e.g., via annotation)
    /** @JMS\Type("App\Entity\Address") */
    private $address;
    
  • Collections:
    $serializer->serialize($user->roles, 'json', [
        'groups' => ['role:read']
    ]);
    

4. Custom Handlers

  • Handler for Custom Types:
    use JMS\Serializer\Handler\SubscribingHandlerInterface;
    
    class CustomHandler implements SubscribingHandlerInterface {
        public static function getSubscribingMethods() {
            return [
                [
                    'direction' => SerializationDirection::DESERIALIZATION,
                    'format' => 'json',
                    'type' => 'App\Entity\CustomType',
                    'method' => 'deserializeCustomType'
                ]
            ];
        }
    
        public function deserializeCustomType($format, $data, array $config) {
            return new CustomType($data['value']);
        }
    }
    
  • Register Handler:
    # config/packages/jms_serializer.yaml
    jms_serializer:
        handlers:
            custom_handler:
                type: App\Serializer\Handler\CustomHandler
    

5. Versioning

  • Context-Based Versioning:
    $context = new SerializationContext();
    $context->setAttribute('version', 'v2');
    $serializer->serialize($data, 'json', $context);
    
  • Metadata Versioning:
    # src/Metadata/Version2/User.yml
    App\Entity\User:
        exclusion_policy: ALL
        properties:
            id:
                expose: true
            name:
                expose: true
                groups: [v2]
    

6. Circular References

  • Automatic Handling: The serializer handles circular references by default. For custom logic:
    $context = new SerializationContext();
    $context->setMaxDepth(5); // Limit recursion depth
    

7. XML Serialization

$xml = $serializer->serialize($data, 'xml', [
    'xml_root_node_name' => 'root',
    'xml_format_output' => true
]);

Integration Tips

Laravel-Specific Patterns

  1. Service Provider Binding: Bind the serializer to the container in AppServiceProvider:

    public function register() {
        $this->app->singleton('jms_serializer', function () {
            return SerializerBuilder::create()
                ->configureHandlers(function (HandlerRegistry $registry) {
                    $registry->registerSubscribingHandler(new CustomHandler());
                })
                ->build();
        });
    }
    
  2. Middleware for API Responses:

    namespace App\Http\Middleware;
    
    use Closure;
    use JMS\Serializer\SerializerInterface;
    
    class SerializeResponseMiddleware {
        protected $serializer;
    
        public function __construct(SerializerInterface $serializer) {
            $this->serializer = $serializer;
        }
    
        public function handle($request, Closure $next) {
            $response = $next($request);
            if ($response->isJson()) {
                $data = json_decode($response->getContent(), true);
                $response->setContent($this->serializer->serialize($data, 'json'));
            }
            return $response;
        }
    }
    
  3. Form Request Validation: Use the serializer to deserialize and validate incoming requests:

    use JMS\Serializer\Exception\RuntimeException;
    
    public function validate() {
        try {
            $data = $this->serializer->deserialize(
                $this->request->getContent(),
                'App\Entity\User',
                'json'
            );
            $this->merge($data);
        } catch (RuntimeException $e) {
            $this->fail('Invalid data format.');
        }
    }
    

Performance Optimization

  1. Metadata Caching: Enable caching in config/packages/jms_serializer.yaml:

    jms_serializer:
        metadata:
            cache: file
            file_cache:
                dir: '%kernel.cache_dir%/serializer'
    
  2. Group Preloading: Preload groups in the constructor of your service:

    public function __construct(SerializerInterface $serializer) {
        $this->serializer = $serializer;
        $this->serializer->getMetadataFactory()->getMetadataFor('App\Entity\User');
    }
    

Gotchas and Tips

Pitfalls

  1. Circular Reference Limits:

    • Issue: Infinite loops during serialization of deeply nested objects.
    • Fix: Set a recursion limit in the SerializationContext:
      $context = new SerializationContext();
      $context->setMaxDepth(10);
      
  2. Annotation vs. YAML/XML Metadata:

    • Issue: Conflicts between annotation-based and YAML/XML metadata definitions.
    • Fix: Ensure consistent metadata sources. Prioritize YAML/XML over annotations if conflicts arise:
      # config/packages/jms_serializer.yaml
      jms_serializer:
          metadata:
              directories:
                  - { path: '%kernel.project_dir%/config/serializer', namespace_prefix: 'App\Metadata' }
              cache: file
      
  3. Doctrine Proxy Objects:

    • Issue: Serialization of Doctrine proxies may fail or include lazy-loaded properties.
    • Fix: Use DoctrineObjectConstructor and exclude lazy properties:
      $context = new SerializationContext();
      $context->setAttribute('exclude_null', true);
      $context->setAttribute('exclude_empty', true);
      
  4. Custom DateTime Handling:

    • Issue: Custom DateTimeInterface implementations may not serialize/deserialize correctly.
    • Fix: Register a custom handler:
      $builder->configureHandlers(function (HandlerRegistry $registry) {
          $registry->registerSubscribingHandler(new CustomDateTimeHandler());
      });
      
  5. Group Inheritance:

    • Issue: Groups defined on parent classes may not propagate to child classes.
    • Fix: Explicitly define groups on child classes or use inheritance in metadata:
      # src/Metadata/Child.yml
      App\Entity\Child:
          inheritance:
              type: JOINED
              groups: [parent_groups, child_groups]
      
  6. PHP 8 Attributes:

    • Issue: Attributes may not be recognized if PHP 8 features are not enabled.
    • Fix: Ensure php8_attributes is enabled in config/packages/jms_serializer.yaml:
      jms_serializer:
          metadata:
              enabled_attributes: true
      
  7. Type Mismatches:

    • Issue: Deserialization fails due to type mismatches (e.g., DateTime vs. Carbon).
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport