Skip to content

magicsunday/jsonmapper

JsonMapper: JSON to PHP Object Mapping

Map JSON data to strongly-typed PHP classes using Symfony's PropertyInfo and PropertyAccess components.

CI

PHPStan Max Level PHPUnit 12 Rector 2.0 PSR-12

PHP Version

Latest version License


πŸ“Œ Overview

JsonMapper is a PHP library that maps JSON data to strongly-typed PHP classes (DTOs, value objects, entities) using reflection and PHPDoc annotations. It leverages Symfony's PropertyInfo and PropertyAccess components to provide flexible, extensible JSON-to-PHP object mapping.

Key Value
Package magicsunday/jsonmapper
PHP ^8.3
Main API MagicSunday\JsonMapper
Output Mapped PHP objects + optional MappingReport

❓ What is this?

JsonMapper takes decoded JSON (via json_decode) and hydrates typed PHP objects, including nested objects, collections, enums, DateTime values, and custom types. It supports both lenient and strict mapping modes with detailed error reporting.

🎯 Why does this exist?

Mapping API responses or configuration payloads to typed PHP classes is a common task that involves repetitive boilerplate. JsonMapper automates this with a clean, extensible architecture based on Symfony components, supporting advanced scenarios like polymorphic APIs, custom name conversion, and recursive collection handling.

πŸš€ Usage

composer require magicsunday/jsonmapper

Quick start

namespace App\Dto;

use ArrayObject;

final class Comment
{
    public string $message;
}

/**
 * @extends ArrayObject<int, Comment>
 */
final class CommentCollection extends ArrayObject
{
}

/**
 * @extends ArrayObject<int, Article>
 */
final class ArticleCollection extends ArrayObject
{
}

final class Article
{
    public string $title;

    /**
     * @var CommentCollection<int, Comment>
     */
    public CommentCollection $comments;
}
require __DIR__ . '/vendor/autoload.php';

use App\Dto\Article;
use App\Dto\ArticleCollection;
use MagicSunday\JsonMapper;

$single = json_decode('{"title":"Hello world","comments":[{"message":"First!"}]}', associative: false, flags: JSON_THROW_ON_ERROR);
$list = json_decode('[{"title":"Hello world","comments":[{"message":"First!"}]},{"title":"Second","comments":[]}]', associative: false, flags: JSON_THROW_ON_ERROR);

$mapper = JsonMapper::createWithDefaults();

$article = $mapper->map($single, Article::class);
$articles = $mapper->map($list, Article::class, ArticleCollection::class);

JsonMapper::createWithDefaults() wires the default Symfony PropertyInfoExtractor (reflection + PhpDoc) and a PropertyAccessor. For custom extractors, caching, or a specialised accessor see Manual instantiation.

PHP classes

Annotate all properties with the requested type. For collections, use the phpDocumentor collection annotation type:

/** @var SomeCollection<DateTime> $dates */
/** @var SomeCollection<string> $labels */
/** @var Collection\\SomeCollection<App\\Entity\\SomeEntity> $entities */

πŸ“š Documentation

πŸ› οΈ Development

Prerequisites:

  • PHP ^8.3
  • Extensions: json

Install dependencies:

composer install

Run the mandatory quality gate:

composer ci:test

ci:test includes:

  • Linting (phplint)
  • Unit tests (phpunit)
  • Static analysis (phpstan)
  • Refactoring dry-run (rector --dry-run)
  • Coding standards dry-run (php-cs-fixer --dry-run)
  • Copy/paste detection (jscpd)

🀝 Contributing

See CONTRIBUTING.md for contributor workflow and minimal setup.

If contributions are prepared or modified by an LLM/agent, follow AGENTS.md.

About

JSON to PHP Object Mapping

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors

Languages