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

Jms Converter Laravel Package

ecotone/jms-converter

Ecotone JMS Converter integrates JMS Serializer with Ecotone’s media type conversion, letting you serialize/deserialize commands, events, and query responses using JMS annotations (groups, naming, handlers) for JSON/XML. Works with Symfony, Laravel, or PSR-11.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to Begin

  1. Install Dependencies Add the package and JMS Serializer to your Laravel project:

    composer require ecotone/jms-converter jms/serializer
    
  2. Set Up Ecotone Install Ecotone (if not already present) and configure it for Laravel:

    composer require ecotone/ecotone
    

    Follow the Laravel DDD/CQRS setup guide.

  3. Configure JMS Converter Bind the JMS converter to Ecotone’s media type converter system in your AppServiceProvider:

    use Ecotone\MediaTypeConverter\MediaTypeConverter;
    use Ecotone\MediaTypeConverter\Jms\JmsMediaTypeConverter;
    
    public function register()
    {
        $this->app->singleton(MediaTypeConverter::class, function ($app) {
            $converter = new MediaTypeConverter();
            $converter->addConverter(new JmsMediaTypeConverter());
            return $converter;
        });
    }
    
  4. Annotate a DTO Use JMS annotations on a command, event, or query response:

    use JMS\Serializer\Annotation as JMS;
    
    #[JMS\Type("App\Dto\UserCreatedDto")]
    class UserCreatedDto
    {
        #[JMS\SerializedName("user_id")]
        #[JMS\Groups({"public"})]
        public int $id;
    
        #[JMS\Groups({"internal"})]
        public string $email;
    }
    
  5. First Use Case Publish an event with JMS annotations:

    use Ecotone\Attribute\Event;
    
    #[Event]
    class UserCreated
    {
        public function __construct(public UserCreatedDto $dto) {}
    }
    
    // In a command handler:
    $this->bus->publish(new UserCreated(new UserCreatedDto()));
    

Implementation Patterns

Usage Patterns

  1. Command/Event Serialization Use JMS annotations to control how commands and events are serialized when published or consumed:

    #[Command]
    class CreateUserCommand
    {
        #[JMS\SerializedName("full_name")]
        public string $name;
    }
    
  2. Query Response Serialization Annotate query responses to expose only specific fields to APIs:

    #[Query]
    class GetUserQuery {}
    
    #[JMS\Type("App\Dto\UserDto")]
    class UserDto
    {
        #[JMS\Groups({"api"})]
        public int $id;
    
        #[JMS\Exclude]
        public string $apiToken;
    }
    
    // In a query handler:
    return new UserDto($user->id, $user->apiToken);
    
  3. Serialization Groups Use groups to conditionally include/exclude fields:

    #[JMS\Groups({"public", "internal"})]
    class UserDto { ... }
    
    // Serialize only "public" fields:
    $serializer->serialize($dto, 'json', ['groups' => ['public']]);
    
  4. Custom Type Handlers Register custom handlers for complex types (e.g., DateTime, UUID):

    $serializer->registerHandler(
        new DateTimeHandler(),
        DateTime::class
    );
    

Workflows

  1. Laravel API Integration

    • Use JMS to serialize API responses while keeping internal commands/events separate:
      // Controller
      public function show(User $user)
      {
          return response()->json(
              $this->bus->query(new GetUserQuery($user->id))
          );
      }
      
  2. Event Sourcing

    • Ensure events are serialized consistently for storage/replay:
      #[Event]
      class UserEmailChanged
      {
          #[JMS\Type("DateTime<'Y-m-d\TH:i:sP'>")]
          public Carbon $changedAt;
      }
      
  3. External Integrations

    • Align payloads with external systems (e.g., Kafka, REST APIs):
      #[JMS\XmlRoot("user")]
      class UserDto { ... }
      

Integration Tips

  1. Laravel Service Container Bind the JmsMediaTypeConverter as a singleton and configure it once:

    $this->app->singleton(JmsMediaTypeConverter::class, function ($app) {
        $serializer = SerializerBuilder::create()
            ->addMetadataDir(__DIR__.'/../resources/config/jms', 'App\\')
            ->build();
        return new JmsMediaTypeConverter($serializer);
    });
    
  2. Metadata Configuration Store JMS metadata in resources/config/jms for better organization:

    resources/
    └── config/
        └── jms/
            ├── UserCreatedDto.metadata.php
            └── ...
    
  3. Testing Mock the MediaTypeConverter in tests:

    $converter = $this->createMock(MediaTypeConverter::class);
    $converter->method('convert')->willReturn($expectedDto);
    $this->bus->setMediaTypeConverter($converter);
    
  4. Performance Cache the JMS metadata builder for repeated use:

    $metadataFactory = new MetadataFactory();
    $metadataFactory->setCache(new FileCache(__DIR__.'/cache/jms'));
    

Gotchas and Tips

Pitfalls

  1. Circular References JMS Serializer may fail on circular references (e.g., UserOrder). Use @MaxDepth or @Exclude:

    #[JMS\MaxDepth(1)]
    class User { ... }
    
  2. Annotation Conflicts Avoid mixing JMS annotations with Laravel’s native attributes (e.g., #[JsonSerializable]). Stick to one serialization approach per class.

  3. Laravel Request/Response Interference JMS annotations on request DTOs may conflict with Laravel’s Illuminate\Http\Request. Use separate DTOs for internal messaging vs. HTTP:

    // HTTP Request DTO (no JMS)
    class StoreUserRequest { ... }
    
    // Internal Command DTO (with JMS)
    #[Command]
    class StoreUserCommand { ... }
    
  4. Metadata Caching Clear the JMS metadata cache when annotations change:

    php artisan cache:clear
    
  5. Ecotone Default Converter Override Ensure the JMS converter is registered after Ecotone’s default converter to avoid precedence issues:

    $converter->addConverter(new JmsMediaTypeConverter(), 100); // High priority
    

Debugging

  1. Serialization Errors Enable JMS Serializer debug mode:

    $serializer->setDebug(true);
    

    Check logs for missing metadata or type errors.

  2. Missing Metadata If annotations are ignored, ensure:

    • Metadata directories are correctly configured.
    • Classes are autoloaded (use composer dump-autoload).
  3. Performance Bottlenecks Profile serialization with Xdebug or Blackfire. Optimize with:

    • @JMS\Type hints for complex objects.
    • Caching metadata.

Tips

  1. Leverage Existing Annotations Reuse JMS annotations from existing DTOs to avoid duplication:

    // Existing API DTO (with JMS)
    class UserDto { ... }
    
    // Reuse for Ecotone commands
    #[Command]
    class UpdateUserCommand
    {
        public UserDto $data;
    }
    
  2. Partial Serialization Use @JMS\Groups to expose different views of the same data:

    // API response (public fields only)
    $serializer->serialize($dto, 'json', ['groups' => ['public']]);
    
    // Internal event (all fields)
    $serializer->serialize($dto, 'json', ['groups' => ['internal']]);
    
  3. Custom Naming Strategies Override field names globally:

    $serializer->setPropertyNamingStrategy(new SnakeCaseNamingStrategy());
    
  4. Laravel Validation Combine JMS annotations with Laravel validation:

    #[JMS\SerializedName("user_email")]
    #[Rule(['required', 'email'])]
    public string $email;
    
  5. Ecotone Lite For non-Laravel projects, use Ecotone Lite with JMS:

    $bus = new Bus();
    $bus->setMediaTypeConverter(new MediaTypeConverter([
        new JmsMediaTypeConverter()
    ]));
    
  6. XML Support Enable XML serialization if needed:

    $serializer->setFormat('xml');
    
  7. Type Safety Use @JMS\Type to enforce strict typing:

    #[JMS\Type("string")]
    public string $name;
    
  8. **Exclude

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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky