mittwald/jsonmapping

用于将PHP对象映射到JSON结构的库

v1.5.0 2020-03-05 08:19 UTC

This package is auto-updated.

Last update: 2024-09-05 18:08:02 UTC


README

Build Status

此包包含一个框架,用于将PHP对象映射到任意的JSON结构。

安装

使用Composer安装此包

$ composer require mittwald/php-jsonmapping

使用

映射对象

此包提供的基本接口是Mw\JsonMapping\MappingInterface接口。它表示一个基本的价值映射。

interface MappingInterface
{
  public funcion map($value)
}

此接口最强大的实现是Mw\JsonMapping\ObjectMapping。ObjectMapping用于将PHP对象映射到数组结构(然后可用于JSON序列化)

$customerMapping = new ObjectMapping([
  'customerNumber' => new ObjectGetterMapping('getCustomernumber'),
  'firstName' => new ObjectGetterMapping('getFirstName')
]);
$customerJson = $customerMapping->map($customer);

或者,使用Mw\JsonMapping\MappingBuilder进行更简洁的表达

$m = new MappingBuilder();

$customerMapping = $m->struct([
  'customerNumber' => $m->getter('getCustomernumber'),
  'firstName'      => $m->getter('getFirstName'),
]);

乍一看,此代码类似于以下代码

$customerJson = [
  'customerNumber' => $customer->getCustomernumber(),
  'firstName'      => $customer->getFirstName()
];

然而,ObjectMapping不仅简单地调用getter方法并构建数组。ObjectMapping还处理null对象或getter方法不可用的情况。因此,以下代码是示例的更好等效代码

$customerJson = $customer != null ? [
  'customerNumber' => is_callable([$customer, 'getCustomernumber']) ? $customer->getCustomernumber() : null,
  'firstName' => is_callable([$customer, 'getFirstName']) ? $customer->getFirstName() : null,
] : null;

映射链式

映射也可以链式连接

$customerMapping = new ObjectMapping([
  'customerNumber' => (new ObjectGetterMapping('getCustomernumber'))->then(new IntegerMapping()),
]);

这也可以用于映射子对象

$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')
  ]))
]);

或者,使用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')
  ])
]);

过滤

可以过滤对象映射以获取特定属性

$customerMapping = new ObjectMapping([
  'customerNumber' => new ObjectGetterMapping('getCustomernumber'),
  'firstName'      => new ObjectGetterMapping('getFirstName')
]);

$filteredCustomerMapping = $customerMapping->filter('firstName');

过滤器也可以嵌套,使用FilterSet

$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);

合并

此外,还可以合并对象映射

$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);

汇总

以下列出了所有可用映射的完整示例;同时,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);