pocketmine / netresearch-jsonmapper
netresearch/jsonmapper 的分支,用于 pocketmine/pocketmine-mp 需要的安全修复
Requires
- php: >=7.1
- ext-json: *
- ext-pcre: *
- ext-reflection: *
- ext-spl: *
Requires (Dev)
- phpunit/phpunit: ~7.5 || ~8.0 || ~9.0 || ~10.0
- squizlabs/php_codesniffer: ~3.5
Replaces
- netresearch/jsonmapper: ~4.2.0
- dev-fork
- v4.4.999
- v4.2.1000
- v4.2.999
- v4.2.0
- v4.1.0
- v4.0.0
- v3.1.1
- v3.1.0
- v3.0.0
- v2.1.0
- v2.0.0
- v1.6.0
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.0
- v1.3.0
- v1.2.0
- v1.1.1
- v1.1.0
- v1.0.0
- v0.11.0
- v0.10.0
- v0.9.0
- v0.8.0
- v0.7.0
- v0.6.1
- v0.6.0
- v0.5.0
- v0.4.4
- v0.4.3
- v0.4.2
- v0.4.1
- v0.4.0
- v0.3.0
- v0.2.1
- v0.2.0
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
- dev-dependabot/composer/phpunit/phpunit-tw-11.3.5
- dev-dependabot/composer/phpunit/phpunit-tw-11.3.4
- dev-dependabot/github_actions/actions/cache-4
- dev-dependabot/github_actions/actions/checkout-4
- dev-strict-object-checking
- dev-master
- dev-null-in-arrays
- dev-array-in-string-property-error
This package is auto-updated.
Last update: 2024-09-16 10:49:07 UTC
README
从 JSON 网络服务获取数据,并将其转换为嵌套对象和数组 - 使用您自己的模型类。
从基本对象开始,它将 JSON 数据映射到类属性,将它们转换为正确的基本类型或对象。
它有点像 PHP 的 native SOAP 参数映射 PHP 的 SoapClient
提供的功能,但用于 JSON。它不依赖于任何模式,只依赖于您的 PHP 类定义。
类型检测通过解析类属性的 @var
文档注释以及设置方法中的类型提示来实现。
您不需要通过添加 JSON 专用代码来修改您的模型类;它通过解析已存在的文档注释自动工作。
此库没有依赖。
关键词:反序列化,初始化
内容
优缺点
优点
- IDE 中的自动完成
- 很容易向数据模型类添加便利方法
- 您的 JSON API 可能会改变,但您的模型可以保持不变 - 不会破坏使用模型类的应用程序。
缺点
模型类需要手动编写
由于 JsonMapper 不依赖于任何模式信息(例如来自 json-schema),因此模型类不能自动生成。
用法
基本用法
- 注册一个可以加载 PSR-0 兼容类的自动加载器。
- 创建一个
JsonMapper
对象实例 - 根据您的数据调用
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
接口的类。
示例
来自地址簿网络服务的 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
使用多个来源来检测属性的正确类型
检查设置方法(
set
+ucwords($propertyname)
)。下划线 "
_
" 和破折号 "-
" 会将下一个字母转换为大写。属性foo_bar-baz
导致设置方法setFooBarBaz
。如果方法签名中有类型提示,则使用该类型。
public function setPerson(Contact $person) {...}
检查方法的文档注释以查找
@param $type
注释。/** * @param Contact $person Main contact for this application */ public function setPerson($person) {...}
如果无法检测到类型,则将纯 JSON 值传递给设置方法。
类属性类型(自 PHP 7.4 以来)
public Contact $person;
构造函数属性提升类型(自 PHP 8.0 以来)
public function __construct(protected Contact $person) {}
类属性的
@var $type
文档注释/** * @var \my\application\model\Contact */ public $person;
属性必须是公共的才能直接使用。您还可以使用 $bIgnoreVisibility 来利用受保护的和私有的属性。
如果无法检测到类型,则将纯 JSON 值设置为属性。
如果找不到属性,JsonMapper会尝试以不区分大小写的方式查找该属性。JSON属性
isempty
将被映射到PHP属性isEmpty
。注意
您必须提供完全限定的命名空间,类型才能正常工作。相对类名在当前类命名空间中评估,而不考虑可能存在的任何导入。
PHP不通过反射提供导入;注释文本仅包含类型的文本。出于性能考虑,JsonMapper不会自行解析源代码来检测和扩展任何导入。
支持的类型名称
简单类型
字符串
bool
,boolean
int
,integer
double
,float
数组
对象
混合类型
类名,带有和不带有命名空间
Contact
- 如果JSON值是null
,将抛出异常
简单类型和类名的数组
int[]
Contact[]
多维数组
int[][]
TreeDeePixel[][][]
简单类型和类名的ArrayObjects
ContactList[Contact]
NumberList[int]
带和不带有命名空间的背靠背枚举
Suit:string|Suit:int
- 如果JSON值不在枚举中,将抛出异常
可空类型
int|null
- 如果JSON中的值是null
,则为null
,否则为整数Contact|null
- 如果JSON中的值是null
,则为null
,否则为类型为Contact
的对象
ArrayObjects和扩展类被视为数组。
未指定类型或类型为mixed
的变量将直接设置JSON值,而无需任何转换。
有关更多信息,请参阅phpdoc的类型文档。
简单类型映射
当需要创建对象但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(...);
这将当变量定义为类型为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(...);
可为空
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(...);
您还可以选择自行处理这些属性,通过设置一个指向 可调用 的 $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 为您处理设置器,您可以从 $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(...);
缺失属性
您可以在 PHP 类中的属性上使用 @required
来标记它们为 "必需"。
/** * @var string * @required */ public $someDatum;
当 JSON 数据不包含此属性时,如果激活了 $bExceptionOnMissingData
,JsonMapper 将抛出异常。
$jm = new JsonMapper(); $jm->bExceptionOnMissingData = true; $jm->map(...);
选项 $bRemoveUndefinedAttributes
会导致 JsonMapper 从最终对象中删除未在 JSON 数据中出现的属性。
$jm = new JsonMapper(); $jm->bRemoveUndefinedAttributes = 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)
默认情况下,由于 map()
需要一个对象作为第一个参数,JsonMapper 将抛出异常。您可以通过将 $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。
$ composer require netresearch/jsonmapper
相关软件
替代方案
- Jackson 的数据绑定(Java)
- Johannes Schmitt 序列化器(PHP)
- metassione(PHP)
- Cartographer(PHP)
- 数据传输对象(PHP)
- Valinor(PHP)
- 具有相同名称的 JsonMapper 库,它具有依赖项。
关于 JsonMapper
许可证
JsonMapper 使用 OSL 3.0 许可。
编码风格
JsonMapper 遵循 PEAR 编码标准。