获取从 JSON Web 服务检索的数据并将其转换为嵌套对象和数组 - 使用您自己的模型类。
从基本对象开始,它将 JSON 数据映射到类属性上,将它们转换为正确的简单类型或对象。
它有点像 PHP 的SoapClient为您提供的本机 SOAP 参数映射,但针对的是 JSON。它不依赖于任何模式,只依赖于 PHP 类定义。
类型检测通过解析类属性的类型声明和@var docblock 注释以及 setter 方法中的类型提示来工作。
您不必通过添加 JSON 特定代码来修改模型类;它通过解析已经存在的文档块来自动工作。
该库没有依赖项。
关键词:反序列化、水化
内容
map()模型类需要手写
由于JsonMapper不依赖于任何模式信息(例如来自json-schema),因此无法自动生成模型类。
netresearch/jsonmapperJsonMapper对象实例map或mapArray方法映射一个普通对象:
<?php
require ' autoload.php ' ;
$ mapper = new JsonMapper ();
$ contactObject = $ mapper -> map ( $ jsonContact , new Contact ());
// or as classname
$ contactObject = $ mapper -> map ( $ jsonContact , Contact::class);映射对象数组:
<?php
require ' autoload.php ' ;
$ mapper = new JsonMapper ();
$ contactsArray = $ mapper -> mapArray (
$ jsonContacts , array (), ' Contact '
);除了array()之外,您还可以使用ArrayObject和派生类,以及实现ArrayAccess类。
来自地址簿 Web 服务的 JSON:
{
"name" : "Sheldon Cooper" ,
"address" : {
"street" : "2311 N. Los Robles Avenue" ,
"city" : "Pasadena"
}
}您当地的Contact方式:
<?php
class Contact
{
/**
* Full name
*/
public string $ name ;
public ? Address $ 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 。
如果方法签名中有类型提示,则使用其类型:
公共函数 setPerson(联系人 $person) {...}
检查该方法的文档块是否有@param $type注释:
/**
* @param Contact $person 此应用程序的主要联系人
*/
公共函数 setPerson($person) {...}
如果无法检测到类型,则将纯 JSON 值传递给 setter 方法。
类属性类型(自 PHP 7.4 起):
公共联系人$人;
构造函数属性提升类型(自 PHP 8.0 起):
公共函数 __construct(受保护的联系人 $person) {}
类属性的@var $type docblock注释:
/** * @var myapplicationmodelContact */ 公共$人;
该财产必须是公共的才能直接使用。您还可以使用 $bIgnoreVisibility 来利用受保护的私有属性。
如果无法检测到类型,则该属性将获取纯 JSON 值集。
如果找不到属性,JsonMapper 会尝试以不区分大小写的方式查找该属性。然后,JSON 属性isempty将映射到 PHP 属性isEmpty 。
笔记
您必须提供完全限定的命名空间才能使类型正常工作。相对类名在当前类命名空间的上下文中进行评估,而不考虑可能存在的任何导入。
PHP 不通过反射提供导入;注释文本仅包含类型的文字文本。出于性能原因,JsonMapper 不会自行解析源代码来检测和扩展任何导入。
简单类型
stringbool , booleanint , integerdouble floatarrayobjectmixed类名,带命名空间和不带命名空间
Contact - 如果 JSON 值为null则会抛出异常简单类型和类名的数组:
int[]Contact[]多维数组:
int[][]TreeDeePixel[][][]简单类型和类名的 ArrayObjects:
ContactList[Contact]NumberList[int]支持枚举,带或不带命名空间
Suit:string|Suit:int- 如果枚举中不存在 JSON 值,则会抛出异常
可空类型:
int|null或?int - 如果 JSON 中的值为null ,则将为null ,否则它将是一个整数Contact|null或?Contact - 如果 JSON 中的值为null ,则将为null ,否则它将是Contact类型的对象ArrayObject 和扩展类被视为数组。
无类型或mixed类型的变量将直接获取 JSON 值集,无需任何转换。
有关详细信息,请参阅 phpdoc 的类型文档。
笔记
从版本 5 开始,出于安全原因,此功能默认被禁用。有关详细信息,请参阅 $bStrictObjectTypeChecking。
当要创建对象但 JSON 仅包含简单类型(例如字符串、浮点数、布尔值)时,该值将传递给类的构造函数。例子:
PHP代码:
public DateTime $ date ;JSON:
{ "date" : "2014-05-15" }这将导致调用new DateTime('2014-05-15') 。
当变量被定义为抽象类或接口的对象时,JsonMapper 通常会尝试直接实例化它们并崩溃。
使用 JsonMapper 的$classMap属性,您可以指定应实例化哪些类:
$ jm = new JsonMapper ();
$ jm -> classMap [ ' Foo ' ] = ' Bar ' ;
$ jm -> map (...);当变量定义为Foo类型时,这将创建Bar类型的对象。
如果需要动态确定实际的实现类(例如在联合的情况下),也可以使用可调用对象。映射的类(下面示例中的“Foo”)和 Json 数据作为参数传递到调用中。
$ mapper = function ( $ class , $ jvalue ) {
// examine $class and $jvalue to figure out what class to use...
return ' DateTime ' ;
};
$ jm = new JsonMapper ();
$ jm -> classMap [ ' Foo ' ] = $ mapper ;
$ jm -> map (...);当 JSON 属性为null时,JsonMapper 会引发异常,除非 PHP 类属性具有可为 null 的类型 - 例如Contact|null或?Contact 。
如果您的 API 包含许多可能为null字段,并且您不希望所有类型定义都可为空,请设置:
$ jm -> bStrictNullTypes = false ;从版本 5.0.0 开始,数组中的null值会导致JsonMapper_Exception ,除非类型可为 null - 例如array[?string]或array[string|null] 。
要恢复以前的行为(即使没有声明也允许空值)设置:
$ jm -> bStrictNullTypesInArrays = false ;JsonMapper 的setLogger()方法支持所有 PSR-3 兼容的记录器实例。
记录的事件:
在开发过程中,API 经常发生变化。为了获得有关此类更改的通知,可以将 JsonMapper 配置为在数据丢失或未知的情况下抛出异常。
当 JsonMapper 看到 JSON 数据中未在 PHP 类中定义的属性时,可以通过设置$bExceptionOnUndefinedProperty让它抛出异常:
$ jm = new JsonMapper ();
$ jm -> bExceptionOnUndefinedProperty = true ;
$ jm -> map (...);您还可以选择通过将可调用设置为$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 (...);或者,如果您让 JsonMapper 为您处理 setter,您可以从$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 fixPropName ( $ object , $ propName , $ jsonValue )
{
return ucfirst ( $ propName );
}
$ jm = new JsonMapper ();
$ jm -> undefinedPropertyHandler = ' fixPropName ' ;
$ jm -> map (...);笔记
仅当 $bStrictObjectTypeChecking 保持启用状态时才有效。
PHP 类中的属性可以通过将@required放入其文档块中来标记为“必需”:
/**
* @var string
* @required
*/
public $ someDatum ;当 JSON 数据不包含此属性时,JsonMapper 将在激活$bExceptionOnMissingData时抛出JsonMapper_Exception :
$ jm = new JsonMapper ();
$ jm -> bExceptionOnMissingData = true ;
$ jm -> map (...);选项$bRemoveUndefinedAttributes会导致 JsonMapper 从最终对象中删除属性(如果它们不在 JSON 数据中):
$ jm = new JsonMapper ();
$ jm -> bRemoveUndefinedAttributes = true ;
$ jm -> map (...);您可以通过将$bIgnoreVisibility设置为 true 来允许映射到私有和受保护的属性和 setter 方法:
$ jm = new JsonMapper ();
$ jm -> bIgnoreVisibility = true ;
$ jm -> map (...);当变量的类型是类并且 JSON 数据是简单类型(如string时,JsonMapper 可以在配置时将此值传递给类的构造函数:
$ jm = new JsonMapper ();
$ jm -> bStrictObjectTypeChecking = false ;
$ jm -> map (...);这可用于从日期字符串自动初始化 DateTime 对象。
不过,禁用这种严格的对象类型检查可能会导致问题:
@required属性不会被填充笔记
在版本 5 中默认值从false更改为true以提高安全性。
现在,如果您想将简单类型传递给类构造函数,您必须选择加入。
map()您可能希望将数组数据传递到通过调用获得的map()中
json_decode ( $ jsonString , true )默认情况下,JsonMapper 会抛出异常,因为map()需要一个对象作为第一个参数。您可以通过将$bEnforceMapType设置为false来避免这种情况:
$ jm = new JsonMapper ();
$ jm -> bEnforceMapType = false ;
$ jm -> map (...);JsonMapper 能够在映射完成后直接在每个对象上调用自定义方法:
$ jm = new JsonMapper ();
$ jm -> postMappingMethod = ' afterMapping ' ;
$ jm -> map (...);现在,每个映射对象上都会调用afterMapping() (如果该类具有该方法)。
您可以将其他参数传递给映射后回调:
$ jm = new JsonMapper ();
$ jm -> postMappingMethod = ' afterMapping ' ;
$ jm -> postMappingMethodArguments = [ 23 , ' foo ' ];
$ jm -> map (...);通过 Packagist 的 Composer:
$ 作曲家需要 netresearch/jsonmapper
替代方案
JsonMapper 根据 OSL 3.0 获得许可。
JsonMapper 遵循 PEAR 编码标准。
克里斯蒂安·韦斯克 (Christian Weiske),cweiske.de