robtimus/json-object-mapper

该包已被废弃,不再维护。没有建议的替代包。

一个用于将对象映射到 JSON 并从 JSON 映射到对象的库

0.3.1 2018-07-23 16:27 UTC

This package is auto-updated.

Last update: 2022-08-03 19:41:28 UTC


README

将对象转换为 JSON 并从 JSON 转换为对象(分别对应序列化和反序列化)。虽然基于 json_encodejson_decode 构建,但它支持任何类型的对象,而不仅仅是 stdClass

基本用法

ObjectMapper 实例有两个方法

  • toJSON 接收一个对象或数组,并将其序列化为 JSON 字符串。
  • fromJSON 接收一个 JSON 字符串,并将其反序列化为对象或对象数组。必须指定对象的类型,可以是它的完全限定名称,也可以是一个 ReflectionClass 实例。

示例

$mapper = new ObjectMapper();
$json = $mapper->toJSON($object);
$object = $mapper->fromJSON($json, '\MyClass');

JSON 属性映射

默认情况下,包括所有公共属性、获取器(支持 getis 前缀的获取器)和设置器。这些需要使用 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;
    }
}

以下内容受支持

  • 标量类型(booleanboolintegerintfloatdoublestring)。
  • 对象类型。
  • \stdClass.
  • 上述数组的数组;在类型后追加 []

包括和排除 JSON 属性

注意:以下所有注释都位于命名空间 Robtimus\JSON\Mapper\Annotations 中,需要使用 use 语句包含它们,或者使用它们的完全限定名称。

@JSONAccessorType

可以将类注释为 @JSONAccessorType("<ACCESSOR_TYPE>") 以更改自动包含的内容。以下为有效的访问器类型

  • METHOD:包括所有获取器和设置器,即使它们不是公共的。
  • PROPERTY:包括所有属性,即使它们不是公共的。
  • PUBLIC_MEMBER:包括所有公共属性、获取器和设置器。
  • NONE:除非明确包含,否则不包含任何属性、获取器或设置器。如果您想明确包含 JSON 属性,请使用此选项。

@JSONProperty

可以通过使用 @JSONProperty 注释显式包含单个属性、获取器或设置器,即使它通常会被排除。此注释可以接受一个可选的 name 属性来覆盖默认属性名称:@JSONProperty(name = "name")

如果没有给出显式的 JSON 属性名称,它将按照以下方式确定

  • 对于属性,属性名称。
  • 对于获取器和设置器,获取器/设置器名称,去掉开头的 getisset 前缀以及紧随其后的任何下划线,然后将第一个字符转换为小写。如果前缀后的方法名称全部为大写,则将其视为缩写并完全转换为小写(例如 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实例上调用addPropertyensureProperty,这些方法返回添加的属性作为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方法可以接受一个选项掩码。支持的选项相同。