hitrain / jsonmapper
将嵌套JSON结构映射到PHP类
Requires
- php: >=5.6
Requires (Dev)
- phpunit/phpunit: 4.2.*
- squizlabs/php_codesniffer: ~1.5
README
从JSON网络服务获取数据并将其转换为嵌套对象和数组,使用您自己的模型类。
从基本对象开始,它将JSON数据映射到类属性,将它们转换为正确的简单类型或对象。
它有点像PHP的SoapClient提供的本地SOAP参数映射,但用于JSON。它不依赖于任何模式,只依赖于您的PHP类定义。
类型检测通过解析类属性的@var docblock注释以及setter方法中的类型提示来完成。
您不需要通过添加JSON特定代码来修改模型类;它通过解析现有的docblocks自动工作。
关键词:反序列化,活化
内容
利与弊
优点
- IDE中的自动完成
- 轻松向数据模型类添加舒适方法
- 您的JSON API可能发生变化,但模型可以保持不变 - 不会破坏使用模型类的应用程序。
缺点
模型类需要手动编写
由于JsonMapper不依赖于任何模式信息(例如,来自json-schema),因此模型类不能自动生成。
用法
基本用法
- 注册一个可以加载PSR-0兼容类的自动加载器。
- 创建一个
JsonMapper对象实例 - 根据您的数据调用
map或mapArray方法
映射普通对象
<?php require 'autoload.php'; $mapper = new JsonMapper(); $contactObject = $mapper->map($jsonContact, new Contact()); ?>
映射对象数组
<?php require 'autoload.php'; $mapper = new JsonMapper(); $contactsArray = $mapper->mapArray( $jsonContacts, array(), 'Contact' ); ?>
除了array()之外,您还可以使用ArrayObject及其派生类。
示例
来自地址簿网络服务的JSON
{ 'name':'Sheldon Cooper', 'address': { 'street': '2311 N. Los Robles Avenue', 'city': 'Pasadena' } }
您的本地Contact类
<?php class Contact { /** * Full name * @var string */ public $name; /** * @var Address */ public $address; } ?>
您的本地Address类
<?php class Address { public $street; public $city; public function getGeoCoords() { //do something with $street and $city } } ?>
您的应用程序代码
<?php $json = json_decode(file_get_contents('http://example.org/sheldon.json')); $mapper = new JsonMapper(); $contact = $mapper->map($json, new Contact()); echo "Geo coordinates for " . $contact->name . ": " . var_export($contact->address->getGeoCoords(), true); ?>
属性类型映射
JsonMapper使用多个来源来检测属性的正确类型
检查setter方法(
set+ucwords($propertyname))。下划线"
_"和连字符"-"将下一个字母转换为大写。属性foo_bar-baz将导致setter方法setFooBarBaz。如果方法签名中有类型提示,则使用该类型。
public function setPerson(Contact $person) {...}检查方法的docblock以查找
@param $type注释。/** * @param Contact $person Main contact for this application */ public function setPerson($person) {...}如果无法检测到类型,则将纯JSON值传递给setter方法。
类属性的
@var $typedocblock注释/** * @var \my\application\model\Contact */ public $person;
属性必须是公共的才能直接使用。受保护和私有的属性不能设置;您必须为它们提供setter方法。
如果无法检测到类型,则将属性设置为纯JSON值。
如果找不到属性,JsonMapper会尝试以不区分大小写的方式查找属性。因此,JSON属性
isempty将被映射到PHP属性isEmpty。
支持的类型名称
- 简单类型
字符串bool、booleanint、integerdouble、float数组对象
- 类名,带和不带命名空间
Contact- 如果 JSON 值为null,则将抛出异常
- 简单类型和类名的数组
int[]Contact[]
- 多维数组
int[][]TreeDeePixel[][][]
- 简单类型和类名的 ArrayObjects
ContactList[Contact]NumberList[int]
- 可空类型
int|null- 如果 JSON 中的值为null,则将是null,否则将是一个整数Contact|null- 如果 JSON 中的值为null,则将是null,否则将是一个Contact类型的对象
ArrayObjects 和扩展类被视为数组。
没有类型或类型为 mixed 的变量将直接设置 JSON 值,无需任何转换。
有关更多信息,请参阅 phpdoc 的类型文档
不同的属性名
当需要将 JSON 中的不同属性名映射到本地类时
您的本地Contact类
<?php class Contact implements JsonMapperInterface { /** * Full name * @var string */ public $name; /** * define mapping rule with assoc array * @return array */ public function mappingRule() { return [ 'jsonName' => 'name', ]; } } ?>
PHP 代码
$jm = new JsonMapper(); $jm->bUseMappingRule = true; $contact->map($json, new Contact());
获取嵌套属性
获取嵌套属性到根对象属性
您的本地Contact类
<?php class Contact implements JsonMapperInterface { /** * Full name * @var string */ public $name; /** * define mapping rule with assoc array * @return array */ public function mappingRule() { return [ 'jsonObject.nestedJsonObject.jsonName' => 'name', ]; } } ?>
PHP 代码
$jm = new JsonMapper(); $jm->bUseMappingRule = true; $contact->map($json, new Contact());
简单类型映射
当需要创建一个对象,但 JSON 只包含简单类型(例如字符串、浮点数、布尔值)时,此值将传递给类的构造函数。例如
PHP 代码
/** * @var DateTime */ public $date;
JSON
{"date":"2014-05-15"}
这将导致调用 new DateTime('2014-05-15')。
类映射
当变量定义为抽象类或接口的对象时,JsonMapper 通常会直接尝试实例化这些类并崩溃。
使用 JsonMapper 的 $classMap 属性,您可以指定哪些类应该被实例化
$jm = new JsonMapper(); $jm->classMap['Foo'] = 'Bar'; $jm->map(...);
这将创建类型为 Bar 的对象,当变量被定义为类型 Foo 时。
可空
JsonMapper 在 JSON 属性为 null 时抛出异常,除非 PHP 类属性具有可空类型 - 例如 Contact|null。
如果您的 API 包含许多可能为 null 的字段,并且您不希望将所有类型定义都设置为可空,请设置
$jm->bStrictNullTypes = false;
日志记录
JsonMapper 的 setLogger() 方法支持所有 PSR-3 兼容的日志记录实例。
记录的事件
- JSON 数据包含一个键,但类中没有相应的属性或设置方法。
- 由于它们是受保护的或私有的,因此无法从外部设置设置器或属性
处理无效或缺失数据
在开发过程中,API 经常会更改。要通知此类更改,可以配置 JsonMapper 在缺少或尚未知的数据时抛出异常。
未知属性
当 JsonMapper 在 JSON 数据中看到 PHP 类中未定义的属性时,可以通过设置 $bExceptionOnUndefinedProperty 来让它抛出异常
$jm = new JsonMapper(); $jm->bExceptionOnUndefinedProperty = true; $jm->map(...);
您也可以通过将 callable 设置到 $undefinedPropertyHandler 来自己处理这些属性
/** * Handle undefined properties during JsonMapper::map() * * @param object $object Object that is being filled * @param string $propName Name of the unknown JSON property * @param mixed $jsonValue JSON value of the property * * @return void */ function setUndefinedProperty($object, $propName, $jsonValue) { $object->{'UNDEF' . $propName} = $jsonValue; } $jm = new JsonMapper(); $jm->undefinedPropertyHandler = 'setUndefinedProperty'; $jm->map(...);
缺失属性
您可以通过在它们的 docblock 中放置 @required 来将 PHP 类中的属性标记为 "必需的"
/** * @var string * @required */ public $someDatum;
当 JSON 数据不包含此属性时,如果激活了 $bExceptionOnMissingData,JsonMapper 将抛出异常
$jm = new JsonMapper(); $jm->bExceptionOnMissingData = true; $jm->map(...);
私有属性和函数
您可以通过将 $bIgnoreVisibility 设置为 true 允许映射到私有和受保护的属性以及设置方法
$jm = new JsonMapper(); $jm->bIgnoreVisibility = true; $jm->map(...);
简单类型而非对象
当变量的类型是类且 JSON 数据是简单类型(如 string)时,JsonMapper 将此值传递给类的构造函数。
如果您不希望这样做,请将 $bStrictObjectTypeChecking 设置为 true
$jm = new JsonMapper(); $jm->bStrictObjectTypeChecking = true; $jm->map(...);
在这种情况下将抛出异常。
向map()传递数组
您可能希望将调用获取的数组数据传递到 map() 中
json_decode($jsonString, true)
默认情况下,JsonMapper会抛出异常,因为map()需要一个对象作为第一个参数。您可以通过将$bEnforceMapType设置为false来绕过这个问题。
$jm = new JsonMapper(); $jm->bEnforceMapType = false; $jm->map(...);
安装
通过Composer
$ composer require netresearch/jsonmapper
通过PEAR
注意:
从版本1.0.0开始,JsonMapper迁移到了PEAR频道https://zustellzentrum.cweiske.de/
来自我们的PEAR频道
$ pear channel-discover zustellzentrum.cweiske.de $ pear install zz/jsonmapper
相关软件
- Jackson的Java数据绑定
- Johannes Schmitt序列化器用于PHP
- metassione用于PHP
关于JsonMapper
许可
JsonMapper遵循OSL 3.0许可证。
编码风格
JsonMapper遵循PEAR编码标准。