PHPackages                             tnapf/jsonmapper - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. tnapf/jsonmapper

AbandonedArchivedLibrary[Utility &amp; Helpers](/categories/utility)

tnapf/jsonmapper
================

A JSON object mapper

v1.4.0(2y ago)134814MITPHPPHP &gt;=8.1

Since May 23Pushed 2y ago1 watchersCompare

[ Source](https://github.com/tnapf/JsonMapper)[ Packagist](https://packagist.org/packages/tnapf/jsonmapper)[ RSS](/packages/tnapf-jsonmapper/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (5)Dependencies (7)Versions (6)Used By (4)

Tnapf/JsonMapper
================

[](#tnapfjsonmapper)

A JSON Mapper

Installation
============

[](#installation)

```
composer require tnapf/json-mapper
```

Supported Types
===============

[](#supported-types)

- Enums
- Primitives
- Objects
- Arrays
- Custom Types (via CallbackType)

Usage
=====

[](#usage)

Instantiate Mapper
------------------

[](#instantiate-mapper)

```
use Tnapf\JsonMapper\Mapper;

$mapper = new Mapper;
```

Create an abstraction class
---------------------------

[](#create-an-abstraction-class)

```
class User
{
    public int $id;
    public string $username;
    public string $password;
}
```

Convert JSON to array and map the class
---------------------------------------

[](#convert-json-to-array-and-map-the-class)

```
$user = [
    "id" => 1,
    "username" => ":username:",
    "password" => ":password:"
];

$mappedUser = $mapper->map($user, User::class);
```

Typing with Attributes
----------------------

[](#typing-with-attributes)

### Primitive Types

[](#primitive-types)

For primitive types you can use the `PrimitiveArray` attribute on the property

```
use Tnapf\JsonMapper\Attributes\PrimitiveType;
use Tnapf\JsonMapper\Attributes\PrimitiveArrayType;

class User
{
    public int $id;
    public string $username;
    public string $password;

    #[PrimitiveArrayType(name: 'roles', type: PrimitiveType::STRING)]
    public array $roles;
}
```

```
// what the new item will look like
$user = [
    // ...
    'roles' => [':name:', ':name:', ':name:']
];
```

### Object Types

[](#object-types)

If you want the array to have a class, you can use the ObjectArrayType attribute

```
use Tnapf\JsonMapper\Attributes\ObjectArrayType;

class User
{
    public int $id;
    public string $username;
    public string $password;

    #[ObjectArrayType(name: 'roles', type: Role::class)]
    public array $roles;
}

class Role {
    public int $id;
    public string $name;
}
```

```
// what the updated item will look like
$user = [
    // ...
    'roles' => [
        [
            'id' => 1,
            'name' => ':name:'
        ],
        [
            'id' => 2,
            'name' => ':name:'
        ],
        [
            'id' => 3,
            'name' => ':name:'
        ]
    ]
];
```

### Array Enumeration Types

[](#array-enumeration-types)

```
use Tnapf\JsonMapper\Attributes\EnumerationArrayType;

class User {
    public int $id;
    public string $username;
    public string $password;

    #[EnumerationArrayType(name: 'roles', type: Role::class))]
    public array $roles;
}

enum Role: int
{
    case USER = 1;
    case ADMIN = 2;
    case OWNER = 3;
}
```

```
// what the updated item will look like
$user = [
    // ...
    'roles' => [1, 3]
];
```

### CallbackType

[](#callbacktype)

If you need to do something specific to map a class, you can extend the CallbackType class to create a custom type

```
use Attribute;
use ReflectionException;
use Tnapf\JsonMapper\Attributes\MappableType;
use Tnapf\JsonMapper\MapperException;
use Tnapf\JsonMapper\MapperInterface;

#[Attribute(Attribute::TARGET_PROPERTY)]
class FriendsType extends MappableType
{
    public function isType(mixed $data): bool
    {
        if (!is_array($data)) {
            return false;
        }

        foreach ($data as $item) {
            if (!$item instanceof User) {
                return false;
            }
        }

        return true;
    }

    /**
     * @throws ReflectionException
     * @throws MapperException
     */
    public function map(mixed $data, MapperInterface $mapper): mixed
    {
        $friends = [];

        foreach ($data as $item) {
            $friend = $mapper->map(User::class, $item);
            $friends[$friend->username] = $friend;
        }

        return $friends;
    }
}

class User {
    public string $username;
    public string $password;

    #[FriendsType(name: 'friends', nullable: true)]
    public array $friends;
}
```

```
// what the updated item will look like
$user = [
    // ...
    'friends' => [
        [
            'username' => ':username:',
            'password' => ':password:'
        ],
        [
            'username' => ':username:',
            'password' => ':password:'
        ],
        [
            'username' => ':username:',
            'password' => ':password:'
        ]
    ]
];
```

Property Case Conversion
------------------------

[](#property-case-conversion)

Since the common json naming convention is `snake_case` and PHP's is `camelCase` you can use apply an attribute to the class to have the `snake_case` json properties routed to your `camelCase` properties.

```
use Tnapf\JsonMapper\Attributes\SnakeToCamelCase;
use Tnapf\JsonMapper\Attributes\PrimitiveType;
use Tnapf\JsonMapper\Attributes\PrimitiveArrayType;

#[SnakeToCamelCase]
class User
{
    public int $id;
    public string $username;
    public string $password;

    #[PrimitiveArrayType(name: 'all_roles', type: PrimitiveType::STRING)]
    public array $allRoles;
}
```

While allRoles is `camelCase` in the class you can see the JSON below uses `snake_case`

```
{
    "id": 1,
    "username": ":username:",
    "password": "1234",
    "all_roles": [
        "admin",
        "user"
    ]
}
```

###  Health Score

29

—

LowBetter than 59% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity14

Limited adoption so far

Community17

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 86.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~28 days

Total

5

Last Release

975d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c1dc8515485fa64088fdfa03dd0f487d507dc1516824c31be2626a6ee25244dd?d=identicon)[command\_string](/maintainers/command_string)

---

Top Contributors

[![CommandString](https://avatars.githubusercontent.com/u/44886996?v=4)](https://github.com/CommandString "CommandString (68 commits)")[![freezemage0](https://avatars.githubusercontent.com/u/48737675?v=4)](https://github.com/freezemage0 "freezemage0 (7 commits)")[![xHeaven](https://avatars.githubusercontent.com/u/14284867?v=4)](https://github.com/xHeaven "xHeaven (4 commits)")

---

Tags

composerjsonmappingphpphp82

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/tnapf-jsonmapper/health.svg)

```
[![Health](https://phpackages.com/badges/tnapf-jsonmapper/health.svg)](https://phpackages.com/packages/tnapf-jsonmapper)
```

###  Alternatives

[magepow/flipbook

Magento 2 Flipbook

1013.8k](/packages/magepow-flipbook)[palantirnet/drupal-skeleton

A Drupal project template.

141.4k](/packages/palantirnet-drupal-skeleton)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
