mittwald / jsonmapping
Library for mapping PHP objects to JSON structures
Installs: 17 876
Dependents: 0
Suggesters: 0
Security: 0
Stars: 4
Watchers: 7
Forks: 0
Open Issues: 0
Requires
- php: >=5.6
Requires (Dev)
- doctrine/orm: ^2.5
- phpunit/phpunit: ^5.2
Suggests
- doctrine/orm: Used for the Mw\JsonMapping\Doctrine\CollectionMapping mapping
README
This package contains a framework for mapping PHP objects into arbitrary JSON structures.
Installation
Install this package via Composer:
$ composer require mittwald/php-jsonmapping
Usage
Mapping objects
The basic interface provided by this package is the interface
Mw\JsonMapping\MappingInterface
. It models a basic mapping from one value to
another.
interface MappingInterface { public funcion map($value) }
The most powerful implementation of this interface is the
Mw\JsonMapping\ObjectMapping
. The ObjectMapping
is used to map PHP objects
into an array structure (which can then be used for JSON serialization):
$customerMapping = new ObjectMapping([ 'customerNumber' => new ObjectGetterMapping('getCustomernumber'), 'firstName' => new ObjectGetterMapping('getFirstName') ]); $customerJson = $customerMapping->map($customer);
Alternatively, use the Mw\JsonMapping\MappingBuilder
for more concise expressions:
$m = new MappingBuilder(); $customerMapping = $m->struct([ 'customerNumber' => $m->getter('getCustomernumber'), 'firstName' => $m->getter('getFirstName'), ]);
On the first glance, this code is similar to the following
$customerJson = [ 'customerNumber' => $customer->getCustomernumber(), 'firstName' => $customer->getFirstName() ];
However, the ObjectMapping
does more than simply calling getter methods and
building an array from them. The ObjectMapping also handles null objects or
getter methods not being available. So all in all, the following code is a much
better equivalent for the example:
$customerJson = $customer != null ? [ 'customerNumber' => is_callable([$customer, 'getCustomernumber']) ? $customer->getCustomernumber() : null, 'firstName' => is_callable([$customer, 'getFirstName']) ? $customer->getFirstName() : null, ] : null;
Chaining mappings
Mappings can also be chained together:
$customerMapping = new ObjectMapping([ 'customerNumber' => (new ObjectGetterMapping('getCustomernumber'))->then(new IntegerMapping()), ]);
This can also be used to map sub-objects:
$customerMapping = new ObjectMapping([ 'customerNumber' => (new ObjectGetterMapping('getCustomernumber'))->then(new IntegerMapping()), 'address' => (new ObjectGetterMapping('getAddress'))->then(new ObjectMapping([ 'street' => new ObjectGetterMapping('getAddress'), 'housenumber' => new ObjectGetterMapping('getHouseNumber'), 'country' => new ObjectGetterMapping('getCountry') ])) ]);
Alternatively, using the MappingBuilder
:
$customerMapping = $m->struct([ 'customerNumber' => $m->getter('getCustomernumber')->then($m->toInteger()), 'address' => $m->getterAndStruct('getAddress', [ 'street' => $m->getter('getAddress'), 'housenumber' => $m->getter('getHouseNumber'), 'country' => $m->getter('getCountry') ]) ]);
Filtering
Object mappings can be filtered for specific properties:
$customerMapping = new ObjectMapping([ 'customerNumber' => new ObjectGetterMapping('getCustomernumber'), 'firstName' => new ObjectGetterMapping('getFirstName') ]); $filteredCustomerMapping = $customerMapping->filter('firstName');
Filters can also be nested, using the FilterSet
class:
$filter = new FilterSet( 'customerNumber', 'address.country' ); $customerMapping = $m->struct([ 'customerNumber' => $m->getter('getCustomernumber')->then($m->toInteger()), 'address' => $m->getterAndStruct('getAddress', [ 'street' => $m->getter('getAddress'), 'housenumber' => $m->getter('getHouseNumber'), 'country' => $m->getter('getCountry') ])->filter($filter->subFilter('address')) ])->filter($filter);
Merging
Also, object mappings can be merged together:
$customerMapping = new ObjectMapping([ 'customerNumber' => new ObjectGetterMapping('getCustomernumber'), 'firstName' => new ObjectGetterMapping('getFirstName') ]); $advancedCustomerMapping = new ObjectMapping([ 'address' => (new ObjectGetterMapping('getAddress'))->then(new ObjectMapping([ 'street' => new ObjectGetterMapping('getAddress'), 'housenumber' => new ObjectGetterMapping('getHouseNumber'), 'country' => new ObjectGetterMapping('getCountry') ])) ]); $mergedCustomerMapping = $customerMapping->merge($advancedCustomerMapping); $mergedCustomerJson = $mergedCustomerMapping->map($customer);
Putting it all together
Find a complete example of all available mappings below; also, the examples/ folder contains more examples:.
$m = new MappingBuilder(); $customerMapping = $m->struct([ 'customerNumber' => $m->getter('getCustomernumber')->then($m->toInteger()), 'firstName' => $m->getter('getFirstName'), 'lastName' => $m->getter('getLastName'), 'invoices' => $m->getter('getInvoices')->then($m->listing($m->struct([ 'invoiceNumber' => $m->getter('getInvoiceNumber')->then($m->toInteger()), 'price' => $m->getter('getPrice')->then($m->toInteger()) ]))) ]); $addressCustomerMapping = $m->struct([ 'address' => $m->getterAndStruct('getAddress', [ 'street' => $m->getter('getAddress'), 'housenumber' => $m->getter('getHouseNumber'), 'country' => $m->getter('getCountry') ]) ]); $customerJson = $customerMapping ->merge($addressCustomerMapping) ->filter($userFilter) ->map($customer);