Weave 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 Serializer Uuid Bundle Laravel Package

mhujer/jms-serializer-uuid-bundle

Symfony bundle that integrates ramsey/uuid with JMS Serializer, registering handlers to serialize and deserialize UUID objects—including uuid-doctrine types—so your JSON APIs handle UUIDs cleanly without custom visitors.

View on GitHub
Deep Wiki
Context7

Getting Started

This bundle is a thin Symfony bridge: it registers one JMS Serializer subscribing handler that converts Ramsey\Uuid\UuidInterface values to/from strings. There is no bundle configuration to tune — enabling the bundle is the integration.

1. Install (legacy stack only). The last release is from 2016 and pins Symfony 2.7/3.x, jms/serializer 0.16/1.x, and ramsey/uuid 2.x/3.x:

composer require mhujer/jms-serializer-uuid-bundle

On Symfony 4+ or ramsey/uuid 4+, expect composer why-not conflicts. In that case skip the package and copy the handler (see Gotchas).

2. Register the bundle in app/AppKernel.php (the repo predates Flex recipes, so there is no config/bundles.php auto-registration):

public function registerBundles()
{
    return [
        // ...
        new MhujerJmsSerializerUuidBundle(),
    ];
}

3. Verify the handler is tagged as a JMS handler, not merely registered as a service:

bin/console debug:container --tag=jms_serializer.subscribing_handler

4. First use case — round-trip a UUID property through JSON:

use JMS\Serializer\Annotation as Serializer;
use Ramsey\Uuid\UuidInterface;

class User
{
    /**
     * @Serializer\Type("Ramsey\Uuid\UuidInterface")
     */
    private $id;

    public function __construct(UuidInterface $id)
    {
        $this->id = $id;
    }

    public function getId(): UuidInterface
    {
        return $this->id;
    }
}
$json = $serializer->serialize($user, 'json');
// {"id":"9f1c0f2e-4a8b-4c1e-9f7d-2b6a1c8e4d33"}

$user = $serializer->deserialize($json, User::class, 'json');
$user->getId(); // Ramsey\Uuid\Uuid instance

Where to look first: the handler's getSubscribingMethods() in src/ — it defines the exact type string and formats that work. Then Resources/config/services.* for the jms_serializer.subscribing_handler tag, and composer.json for hard version ceilings.

Implementation Patterns

Annotate with the exact subscribed type. The property annotation's type string must match the handler registration exactly. Use @Serializer\Type("Ramsey\Uuid\UuidInterface"); this is the package's entire public API. Deserialization produces the concrete Ramsey\Uuid\Uuid class.

Use input DTOs for request bodies. JMS 1.x does not reliably hydrate constructor arguments, so accept UUIDs on a DTO and map into your immutable entity:

class CreateUserInput
{
    /** @Serializer\Type("Ramsey\Uuid\UuidInterface") */
    public $id;

    /** @Serializer\Type("string") */
    public $name;
}

$input = $serializer->deserialize($request->getContent(), CreateUserInput::class, 'json');
$user = new User($input->id, $input->name);

Keep serialization and Doctrine mapping separate. With ramsey/uuid-doctrine, Doctrine converts the DB column while this handler converts JSON. Both operate on the same UuidInterface field; neither knows about the other. Test both paths independently.

Use a virtual property for output-only string fields. If a consumer expects a plain string and you do not want the handler involved:

/**
 * @Serializer\VirtualProperty
 * @Serializer\SerializedName("id")
 */
public function idAsString(): string
{
    return $this->id->toString();
}

For input, provide a setter that accepts a string and calls Uuid::fromString().

Reuse the handler without booting Symfony in unit tests:

$serializer = \JMS\Serializer\SerializerBuilder::create()
    ->configureHandlers(function (\JMS\Serializer\Handler\HandlerRegistry $registry) {
        $registry->registerSubscribingHandler(new \Mhujer\JmsSerializer\Uuid\UuidSerializerHandler());
    })
    ->build();

$this->assertSame(
    $uuid->toString(),
    json_decode($serializer->serialize(['id' => $uuid], 'json'), true)['id']
);

Round-trip assertions are the cheapest regression test. Serialize a known UUID, decode the JSON, assert the canonical dashed lowercase form, then deserialize and assert instanceof UuidInterface plus value equality.

Error mapping belongs in your API layer. Wrap deserialization or add an exception listener that converts invalid UUID exceptions into HTTP 400 rather than 500.

Gotchas and Tips

  • Archived and abandoned. Last release 2016-06-02, 12 stars, 0 dependents. There will be no fixes. Treat it as a code sample, not a dependency, on any new project.
  • Dependency ceilings are the real blocker. Symfony 2.7/3.x, jms/serializer 0.16/1.x, ramsey/uuid 2/3 only. Do not fight composer; copy the roughly 40-line handler into App\Serializer and tag it:
services:
    App\Serializer\UuidHandler:
        tags:
            - { name: jms_serializer.subscribing_handler }
final class UuidHandler implements SubscribingHandlerInterface
{
    public static function getSubscribingMethods(): array
    {
        $methods = [];
        foreach (['json', 'xml', 'yml'] as $format) {
            $methods[] = [
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'format' => $format,
                'type' => UuidInterface::class,
                'method' => 'serialize',
            ];
            $methods[] = [
                'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
                'format' => $format,
                'type' => UuidInterface::class,
                'method' => 'deserialize',
            ];
        }

        return $methods;
    }

    public function serialize($visitor, UuidInterface $uuid, array $type, Context $context): string
    {
        return $uuid->toString();
    }

    public function deserialize($visitor, string $data, array $type, Context $context): UuidInterface
    {
        return Uuid::fromString($data);
    }
}

On JMS 3.x, GraphNavigator is deprecated in favour of GraphNavigatorInterface; adjust the constants when copying.

  • Type-string mismatch fails confusingly. If the annotation type does not exactly match the subscription, JMS falls back to reflection and tries to instantiate the interface/class, producing "cannot instantiate interface" errors or an unexpected object. Check getSubscribingMethods() first when deserialization misbehaves.
  • Format coverage is narrow. The shipped subscription is commonly JSON-only; XML or YAML serialization silently bypasses the handler. Confirm the format keys before exposing multiple representations. The copied handler above covers JSON, XML, and YAML.
  • Null handling. JMS usually bypasses handlers for null, but if the handler is invoked, a non-nullable type hint throws TypeError. Keep UUID fields nullable where the domain allows it and guard in the handler.
  • Invalid input throws ramsey exceptions, not serializer exceptions. Uuid::fromString() rejects malformed strings with an InvalidArgumentException-family exception (e.g. InvalidUuidStringException). Convert this to a 400 in your API layer; otherwise clients see a 500.
  • fromString() accepts non-canonical forms. Undashed hex and some variants are valid input. If your API contract requires canonical dashed lowercase output, always emit toString() and normalize on input.
  • Symfony 4+ registration is manual. No Flex recipe; add the bundle to config/bundles.php if you insist on using it, and clear the cache after registering so the container picks up the handler tag.
  • Zero adoption is a signal. With no dependents, there is no community pressure to keep it compatible. The handler is small enough to own; vendor it into your application and add a round-trip test rather than pinning a dead package.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings