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

Jsonapi Mapper Laravel Package

uni-method/jsonapi-mapper

A Laravel package for mapping Eloquent models to JSON:API resources. Define resource classes covering attributes, relationships and links, then transform models into spec-compliant JSON:API documents with consistent, predictable serialization.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a micro-package (3 stars, no dependents, single maintainer org). Treat the first hour as due diligence, not integration.

1. Install and pin

composer require uni-method/jsonapi-mapper

Before writing any code, open vendor/uni-method/jsonapi-mapper/ and read three things in this order:

  • composer.json — PHP constraint, autoload prefixes, and whether it declares a Laravel service provider / facade
  • src/ — the entire source is likely a handful of classes; read all of it
  • tests/ (or its absence) — no tests is a strong signal about edge-case behavior

2. Find the entry point

You are looking for the mapper's primary public API: typically a Mapper/JsonMapper class with a method that takes a decoded array or JSON string plus a target class name, and returns a hydrated object. If the package ships a Laravel provider, check config/ for published options; if it does not, you will instantiate the mapper yourself.

3. First use case: hydrate one DTO at the HTTP boundary

// app/Dto/OrderDto.php
final class OrderDto
{
    public function __construct(
        public readonly string $id,
        public readonly string $status,
        public readonly ?string $customerEmail = null,
    ) {}
}
// app/Http/Controllers/WebhookController.php
$dto = app(JsonMapper::class)->map(
    $request->json()->all(),
    OrderDto::class,
);

return response()->noContent();

Verify behavior in Tinker before wiring it into a controller — mapping libraries differ sharply on missing keys, type coercion, and nested objects, and you want to see those failures on a REPL, not in a webhook handler.

Implementation Patterns

Keep the mapper at the boundary only. Do not let mapped DTOs leak into Eloquent models, jobs, or domain services as the canonical representation. Map incoming JSON → DTO → domain command, and domain object → array → JsonResource on the way out. If you find yourself calling the mapper inside a service class, you have coupled your domain to a 3-star dependency.

Bind it, don't new it. Whatever the mapper's constructor looks like, register it once:

// app/Providers/AppServiceProvider.php
$this->app->singleton(\UniMethod\JsonApiMapper\Mapper::class, function () {
    return new \UniMethod\JsonApiMapper\Mapper(/* options */);
});

A container binding is your escape hatch: when the package stalls (see Gotchas), you swap the binding for an adapter over cweiske/jsonmapper or spatie/laravel-data and touch one file instead of fifty.

Wrap it in a thin application-level adapter. Even if the package API is convenient, define your own JsonHydrator interface with hydrate(array $payload, string $class): object and implement it with the package. This costs ~20 lines and buys you testability, since you can fake the hydrator in feature tests without the package's quirks.

Per-endpoint DTOs, one mapper config. Different integrations have different casing and nullability conventions. Rather than trying to configure one global mapper for everything, keep DTO classes explicit per integration (Stripe/InvoiceDto, Internal/InvoiceDto) and let the mapper's default behavior handle the common case. Explicit constructors with readonly properties give you PHP-level validation for free.

Validate before you map. The mapper converts shape; it does not enforce business rules. Run Validator::make($request->all(), $rules) first, then map the validated array. Mapping unvalidated input means a malformed payload surfaces as a TypeError deep inside the package with a useless stack trace.

Test the round trip, not the internals. Assert on the DTO's property values and on the JSON your API returns. Do not unit test the mapper itself — you do not own it, and its behavior may change when you eventually replace it.

Gotchas and Tips

Maintenance risk is the headline. Three stars and zero dependents means you are likely one of a very small number of users. Before shipping, check the last commit date and open issues. If the repo has been quiet for 12+ months, plan for one of: (a) vendor the source into app/Support/JsonMapper/ under your own namespace, (b) wrap it behind the adapter interface above so replacement is cheap, or (c) skip it entirely and use symfony/serializer or spatie/laravel-data, both of which handle the same job with real maintenance and Laravel-native ergonomics.

Type coercion is where mappers silently lie. Confirm what happens when JSON contains "42" for an int property, null for a non-nullable one, or a key that is absent versus present-and-null. Many small mappers use reflection without strict types and will happily assign "42" to an int $id — which then fails much later. If the package has no strict mode, add a post-map assertion pass, or cast explicitly in your DTO's fromArray static.

Nested objects and collections are usually the weakest area. Test a nested object and a list<Dto> in Tinker early. If arrays-of-objects are unsupported, you will need a manual loop, and that is a good moment to reconsider the dependency.

Mass-assignment surface. A reflection-based mapper may write to any property it can name, including ones you did not intend to expose. Keep DTOs readonly and constructor-only so unknown keys become an error rather than a silent write. Never map directly into an Eloquent model.

Casing mismatches. PHP properties are typically camelCase; JSON payloads are often snake_case. Find the package's key-transformation option (or custom name-mapping hook) before hand-writing accessor boilerplate in every DTO.

Dates and enums. Verify whether the mapper handles DateTimeImmutable and PHP backed enums, or whether it requires a string property plus a cast in your DTO. This is a frequent gap in minimal mappers.

Debugging technique. When a hydration fails, dump both sides:

dump($payload, $dto ?? null); // then dd() the caught exception

Most failures are a key-name mismatch or a null where the constructor forbids it — the package's exception message often will not say which. Wrap the call in try/catch (\Throwable $e) in your adapter and rethrow with the payload keys attached so the log is actionable.

Extension points to look for. If the mapper offers custom type handlers, normalizers, or a map() callback per property, that is your lifeline for special cases (money objects, UUID value objects). If it offers none, budget for pre-processing the array into a flat, mapper-friendly shape before hydration — that preprocessor is where all your integration-specific weirdness should live.

Lock the version exactly. With no dependents, semantic-versioning discipline is unproven. Use "uni-method/jsonapi-mapper": "1.0.*" or a commit hash rather than ^1.0, and commit composer.lock.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource