robtimus / json-object-mapper
一个用于将对象映射到 JSON 并从 JSON 映射到对象的库
Requires
- php: >=5.3.2
- doctrine/annotations: >=1.2.7
- doctrine/cache: >=1.5.4
Requires (Dev)
- phpunit/phpunit: ~4
This package is auto-updated.
Last update: 2022-08-03 19:41:28 UTC
README
将对象转换为 JSON 并从 JSON 转换为对象(分别对应序列化和反序列化)。虽然基于 json_encode 和 json_decode 构建,但它支持任何类型的对象,而不仅仅是 stdClass。
基本用法
ObjectMapper
实例有两个方法
toJSON
接收一个对象或数组,并将其序列化为 JSON 字符串。fromJSON
接收一个 JSON 字符串,并将其反序列化为对象或对象数组。必须指定对象的类型,可以是它的完全限定名称,也可以是一个 ReflectionClass 实例。
示例
$mapper = new ObjectMapper();
$json = $mapper->toJSON($object);
$object = $mapper->fromJSON($json, '\MyClass');
JSON 属性映射
默认情况下,包括所有公共属性、获取器(支持 get
和 is
前缀的获取器)和设置器。这些需要使用 phpDocumenter 注释指定它们的类型。例如
class Person {
/**
* @var string
*/
public $firstName;
private $lastName;
/**
* @return string
*/
public function getLastName() {
return $this->lastName;
}
/**
* @param string $value
*/
public function setLastName($value) {
$this->lastName = $value;
}
}
以下内容受支持
- 标量类型(
boolean
、bool
、integer
、int
、float
、double
、string
)。 - 对象类型。
\stdClass
.- 上述数组的数组;在类型后追加
[]
。
包括和排除 JSON 属性
注意:以下所有注释都位于命名空间 Robtimus\JSON\Mapper\Annotations
中,需要使用 use
语句包含它们,或者使用它们的完全限定名称。
@JSONAccessorType
可以将类注释为 @JSONAccessorType("<ACCESSOR_TYPE>")
以更改自动包含的内容。以下为有效的访问器类型
METHOD
:包括所有获取器和设置器,即使它们不是公共的。PROPERTY
:包括所有属性,即使它们不是公共的。PUBLIC_MEMBER
:包括所有公共属性、获取器和设置器。NONE
:除非明确包含,否则不包含任何属性、获取器或设置器。如果您想明确包含 JSON 属性,请使用此选项。
@JSONProperty
可以通过使用 @JSONProperty
注释显式包含单个属性、获取器或设置器,即使它通常会被排除。此注释可以接受一个可选的 name
属性来覆盖默认属性名称:@JSONProperty(name = "name")
。
如果没有给出显式的 JSON 属性名称,它将按照以下方式确定
- 对于属性,属性名称。
- 对于获取器和设置器,获取器/设置器名称,去掉开头的
get
、is
或set
前缀以及紧随其后的任何下划线,然后将第一个字符转换为小写。如果前缀后的方法名称全部为大写,则将其视为缩写并完全转换为小写(例如getURL
=>url
)。
@JSONIgnore
通过使用@JSONIgnore
注解,可以忽略单个属性、getter或setter,即使它们通常会被包含(这将覆盖@JSONProperty
)。
@JSONReadOnly
可以通过使用@JSONReadOnly
注解将单个属性设置为只读(即在反序列化期间将被忽略)。同样,通过将属性设置为私有并提供仅getter的方法,或者通过注解setter为@JSONIgnore
,也可以达到同样的效果。
@JSONWriteOnly
可以通过使用@JSONWriteOnly
注解将单个属性设置为只写(即在序列化期间将被忽略)。同样,通过将属性设置为私有并提供仅setter的方法,或者通过注解getter为@JSONIgnore
,也可以达到同样的效果。
@JSONAnyGetter
可以注解一个不接受任何参数并返回关联数组、stdClass
实例或迭代器的单个方法,使用@JSONAnyGetter
。返回值的键和值将在序列化过程中添加到JSON字符串中。
忽略null
值和/或空数组
将ObjectMapper
实例的omitNullValues
属性设置为true
,以忽略具有null
值的JSON属性。
将ObjectMapper
实例的omitEmptyArrays
属性设置为true
,以忽略具有空数组值的JSON属性。
JSON属性顺序
默认情况下,在序列化期间JSON属性将具有不确定的顺序。可以通过使用@JSONPropertyOrder
注解为类创建特定的顺序。此注解可以使用两种方式使用
@JSONPropertyOrder(alphabetical = true)
以使用字母顺序。@JSONPropertyOrder(properties = {"property1", "property2", ...})
以指定所需的顺序。请注意,此列表必须包含所有JSON属性,包括继承的JSON属性。
请注意,此属性顺序不包括由注解了@JSONAnyGetter
的方法返回的属性。
处理未知属性
默认情况下,在将JSON字符串反序列化为对象时,任何在对象中未定义的JSON属性将导致抛出JSONParseException
。可以通过以下两种方式之一防止这种情况
- 将
ObjectMapper
实例的allowUndefinedProperties
属性设置为true
。这将导致忽略任何未定义的JSON属性。 - 提供一个接受两个参数(JSON属性名称及其值)的单个方法,并使用
@JSONAnySetter
注解它。此方法将为每个未知JSON属性及其值被调用。
自定义序列化和反序列化
默认情况下,标量值将按原样使用,对象将按上述方式处理。可以通过提供自定义序列化器或反序列化器来更改此行为。
自定义序列化
可以通过实现JSONSerializer
来创建自定义序列化器,并且可以以两种方式为JSON属性定义自定义序列化器
-
使用
@JSONSerialize(using = "<JSONSerializer class name>")
注解属性或getter,可以为单个属性或getter使用自定义序列化器。 -
在
ObjectMapper
实例上调用setDefaultSerializer
,可以为特定类型的所有JSON属性使用自定义序列化器。例如,要为所有DateTime
JSON属性使用DateTimeJSONSerializer
$mapper->setDefaultSerializer('\DateTime', new DateTimeJSONSerializer(DateTime::RFC3339_EXTENDED));
自定义序列化
可以通过实现JSONDeserializer
创建自定义反序列化器,并且可以通过两种方式为JSON属性定义它
-
使用
@JSONDeserialize(using = "<JSONDeserializer class name>")
注解属性或setter,可以为单个属性或setter使用自定义反序列化器。 -
在
ObjectMapper
实例上调用setDefaultDeserializer
,可以为特定类型的所有JSON属性使用自定义反序列化器。例如,要为所有DateTime
JSON属性使用DateTimeJSONDeserializer
$mapper->setDefaultDeserializer('\DateTime', new DateTimeJSONDeserializer(DateTime::RFC3339_EXTENDED));
程序化映射
除了使用注解,还可以通过创建ClassDescriptor
并添加属性来程序化地创建类的映射。然后可以使用其registerClass
方法将其添加到ObjectMapper
实例。
以下是将注解映射到替换它们的方法的示例
@JSONAccessorType
:没有替换,因为程序化映射替换了所有自动包含JSON属性。@JSONProperty
:在ClassDescriptor
实例上调用addProperty
或ensureProperty
,这些方法返回添加的属性作为PropertyDescriptor
的实例。名称和类型是必需的;类型可以是相对于一个可选的第三个参数的类型ReflectionClass
。@JSONIgnore
:没有替换,因为程序化映射只添加要包含的属性。@JSONReadOnly
:不要在添加的属性上调用withSetter
。@JSONWriteOnly
:不要在添加的属性上调用withGetter
。@JSONAnyGetter
:在ClassDescriptor
实例上调用withAnyGetter
。此方法是累加的,因此可以指定多个方法。@JSONAnySetter
:在ClassDescriptor
实例上调用withAnySetter
。@JSONPropertyOrder
:在ClassDescriptor
实例上调用orderProperties
。提供一个包含要排序的JSON属性的数组,或提供无参数以使用字母顺序。@JSONSerialize
:在添加的属性上调用withSerializer
。@JSONDeserialize
:在添加的属性上调用withDeserializer
。
请注意,所有getter和setter都是可调用的。这消除了使用实例方法的必要性。
示例
$classDescriptor = new ClassDescriptor(new ReflectionClass('\Person'));
$classDescriptor->addProperty('firstName', 'string')
->withGetter(array(new ReflectionProperty('\Person', 'firstName'), 'getValue'))
->withSetter(array(new ReflectionProperty('\Person', 'firstName'), 'setValue'));
$classDescriptor->addProperty('lastName', 'string')
->withGetter(array(new ReflectionMethod('\Person', 'getLastName'), 'invoke'))
->withSetter(array(new ReflectionMethod('\Person', 'setLastName'), 'invoke'));
$mapper->registerClass($classDescriptor);
格式化
与json_encode类似,ObjectMapper
实例的toJSON
方法可以接受一个选项掩码。支持的选项相同。