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

Array Jms Serializer Bundle Laravel Package

epwt/array-jms-serializer-bundle

A Symfony bundle that extends JMSSerializerBundle with an Array format, letting you serialize and deserialize data to and from PHP arrays alongside the formats JMS already supports. A small add-on for projects needing array output within the JMS serialization pipeline.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Pull it in via Composer. The bundle is an extension of JMSSerializerBundle, so it does not replace it:

    composer require epwt/array-jms-serializer-bundle
    

    Confirm jms/serializer-bundle and jms/serializer are also in composer.json — this package only adds a format visitor on top of them.

  2. Register the bundle. On Symfony Flex (4.x/5.x) add it to config/bundles.php:

    return [
        // ...
        JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true],
        EPWT\ArrayJMSSerializerBundle\EPWTArrayJMSSerializerBundle::class => ['all' => true],
    ];
    

    On legacy Symfony, add both to AppKernel::registerBundles(). Order matters: register the EPWT bundle after JMSSerializerBundle so the array visitors attach to an already-initialised serializer.

  3. Where to look first. Open vendor/epwt/array-jms-serializer-bundle/ and read DependencyInjection/ and the Resources/config/services.* files. There is essentially no documentation in the README, so the service definitions and compiler pass (if any) are your only real spec. Look for the format name it registers — in practice it is the string "array".

  4. First use case. Inject JMS\Serializer\SerializerInterface and request the "array" format instead of "json":

    use JMS\Serializer\SerializerInterface;
    
    final class UserPresenter
    {
        public function __construct(private SerializerInterface $serializer) {}
    
        public function present(User $user): array
        {
            return $this->serializer->serialize($user, 'array');
        }
    }
    

    serialize() now returns a PHP array (scalars, nested arrays, list arrays) rather than a JSON string. From there you can json_encode() it yourself, pass it to a template, put it in an array cache, or feed it to a normaliser.

  5. Smoke test before trusting it in code paths:

    dump($this->serializer->serialize($user, 'array'));
    

    If you get a RuntimeException about an unknown format, the bundle is not registered or its compiler pass is not running — see Gotchas.


Implementation Patterns

Controller-level response shaping

The most common day-to-day pattern is bypassing JMSSerializer's View/response listener and returning arrays directly. Because you now own the array, you can merge, filter, or paginate it without a decode step:

$payload = $serializer->serialize($users, 'array');
$payload['meta'] = ['total' => count($users)];

return $this->json($payload);

This is where the package pays for itself: no string encode → decode round-trip.

Deserialising incoming arrays

The reverse direction is the more fragile half. deserialize($array, User::class, 'array') works, but only when your DTOs carry enough type metadata (annotations/attributes) for the visitor to reconstruct nested objects:

$user = $serializer->deserialize($requestArray, User::class, 'array', DeserializationContext::create()
    ->setGroups(['input']));

Use this for internal pipelines — queue messages you have already serialised, cache warming, fixtures — rather than for raw request bodies. For HTTP input, stay on json so field types and formats come from a well-tested decoder.

DTO / transformation layer

Treat the array format as the engine behind a presenter layer:

class OrderPresenter
{
    public function __construct(private SerializerInterface $serializer) {}

    public function toArray(Order $order): array
    {
        return $this->serializer
            ->serialize($order, 'array', SerializationContext::create()->setGroups(['api']));
    }
}

Your service classes no longer return string; they return array, which is easier to type against, assert on in PHPUnit, and compose with array_map/array_filter.

Groups, @Type, @VirtualProperty, naming strategies

Everything that works for JSON works here because JMS delegates to the same metadata graph. If you already use #[Groups], #[SerializedName], or custom naming strategies, keep them — you only change the format argument. This is the main argument for choosing this bundle over hand-rolling an array mapper.

Testing

Arrays are far nicer to assert on than JSON strings:

$data = $serializer->serialize($order, 'array');
$this->assertSame('ORD-123', $data['id']);
$this->assertCount(2, $data['items']);

No json_decode in every test, and failures point at the exact key.

Caching

Because the result is a plain PHP array, it drops cleanly into var_export-generated cache files or an array-backed cache pool. Do not cache the output if it contains objects (see Gotchas).


Gotchas and Tips

  • The format string is "array" (lowercase). If jms_serializer config has a whitelist of formats anywhere (format_listener, handlers, custom format registries), add it explicitly. The bundle registers the visitors, not the format name in every consumer.

  • Arrays lose type information. After serialising, an Address object becomes a nested array. On the way back in, JMS can only rebuild it if the parent property declares the type (@Type("App\Entity\Address") / #[Type(Address::class)]) or the property is typed and JMS can reflect it. Without metadata, deserialize() will quietly hand you an array where you expected an object, or throw — both are confusing. This is the #1 source of bugs with array-format round-trips.

  • Objects can leak into the output. Depending on visitor behaviour and your handler setup, values that cannot be converted to scalars (e.g. DateTimeImmutable without a handler, or an object held via a circular-reference handler) may remain as live PHP objects inside the array. Always inspect with dump() when wiring up new entities. If you json_encode() such an array, you will silently serialise public properties rather than going through JMS.

  • Circular references need a handler. Same as JSON:

    $ctx = SerializationContext::create()
        ->setSerializeNull(true);
    $ctx->setCircularReferenceHandler(fn ($o) => $o->getId());
    

    Without one you get an CircularReferenceException — or, worse in array mode, a nested structure that is very hard to trace.

  • Collections and empty values. ArrayCollection empty → []; missing property → null; untyped scalar → possibly null. If downstream code distinguishes “empty” from “missing”, make it explicit in the DTO or use setSerializeNull(true) and be consistent.

  • Register bundle order. Because this bundle extends the JMS one, put it after JMSSerializerBundle. In legacy AppKernel this is easy to get wrong and produces a “no visitor for format array” error.

  • Maintenance risk. With 4 stars and a README-only docs state, assume the package is frozen. Pin the version in composer.json, and check compatibility with your installed jms/serializer and Symfony versions before upgrading either. If the visitor fails on a newer JMS major, you can generally replicate its behaviour by calling the JSON visitor and decoding, or by writing a tiny custom visitor — which is worth knowing before you depend on it heavily.

  • Don’t mix with Symfony’s ArrayDenormalizer. If you use both the Symfony Serializer component (with ArrayDenormalizer/JsonEncoder) and JMS array format, you have two deserialisers with different metadata semantics. Pick one per boundary (e.g. Symfony for HTTP, JMS array for internal DTOs) and be explicit in the service wiring.

  • Debugging tip. When a field is wrong, serialise to "json" and to "array" and diff them. If the JSON contains the field but the array does not, the problem is in a handler that only supports JSON output; if both are missing, it is a metadata/group issue and unrelated to this bundle.

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.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json