如何使用序列化(Serializer)

一个对象和不同格式(比如JSON或XML)之间的序列化和反序列化是一个非常复杂的话题。Symfony自带了一个Serializer组件,给你提供了一些工具,可以随需利用。

实际上,在你开始使用之前,先熟悉一下serializer,normalizer和encoder,请阅读Serializer组件一文。

激活Serializer 

serializer服务默认不可用。要开启它,在你的配置文件中激活它:

1
2
3
4
5
# app/config/config.yml
framework:
    # ...
    serializer:
        enabled: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:framework="http://symfony.com/schema/dic/symfony"
    xmlns:twig="http://symfony.com/schema/dic/twig"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/symfony
        http://symfony.com/schema/dic/symfony/symfony-1.0.xsd
        http://symfony.com/schema/dic/twig
        http://symfony.com/schema/dic/twig/twig-1.0.xsd">
    <framework:config>
        <!-- ... -->
        <framework:serializer enabled="true" />
    </framework:config>
</container>
1
2
3
4
5
6
7
// app/config/config.php
$container->loadFromExtension('framework', array(
    // ...
    'serializer' => array(
        'enabled' => true,
    ),
));

使用Serializer服务 

一旦开启,serializer服务可以在你需要它时注入到任何服务中,或者像下面这样在控制器中使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/AppBundle/Controller/DefaultController.php
namespace AppBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
 
class DefaultController extends Controller
{
    public function indexAction()
    {
        $serializer = $this->get('serializer');
 
        // ...
    }
}

添加Normalizers和Encoders 

被开启之后,serializer在容器中可用,被加载时还带有两个encodersJsonEncoderXmlEncoder)以及ObjectNormalizer normalizer

你可以加载normalizers和/或encoders,只要给它们打上 serializer.normalizerserializer.encoder 标签。也可以设置标签的优先级,以便决定匹配顺序。

下例演示了如何加载GetSetMethodNormalizer

1
2
3
4
5
6
7
# app/config/services.yml
services:
    get_set_method_normalizer:
        class: Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer
        public: false
        tags:
            - { name: serializer.normalizer }
1
2
3
4
5
6
<!-- app/config/services.xml -->
<services>
    <service id="get_set_method_normalizer" class="Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer" public="false">
        <tag name="serializer.normalizer" />
    </service>
</services>
1
2
3
4
5
6
7
8
9
// app/config/services.php
use Symfony\Component\DependencyInjection\Definition;
 
$definition = new Definition(
    'Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer'
));
$definition->setPublic(false);
$definition->addTag('serializer.normalizer');
$container->setDefinition('get_set_method_normalizer', $definition);

使用序列化的群组Annotations 

通过以下配置来开启序列化群组注释

1
2
3
4
5
# app/config/config.yml
framework:
    # ...
    serializer:
        enable_annotations: true
1
2
3
4
5
<!-- app/config/config.xml -->
<framework:config>
    <!-- ... -->
    <framework:serializer enable-annotations="true" />
</framework:config>
1
2
3
4
5
6
7
// app/config/config.php
$container->loadFromExtension('framework', array(
    // ...
    'serializer' => array(
        'enable_annotations' => true,
    ),
));

接下来,添加 @Goups annotations 到你的类中,然后在序列化时,选择要使用哪个群组:

1
2
3
4
5
$serializer = $this->get('serializer');
$json = $serializer->serialize(
    $someObject,
    'json', array('groups' => array('group1'))
);

除了 @Groups 注释,serializer组件还支持Yaml或Xml文件。这些组件在存放于以下位置时将被自动加载:

  • 存放在bundle下面的 Resources/config/ 目录中的 serialization.ymlserialization.xml

  • 存放在bundle下面的 Resources/config/serialization/ 目录中的所有 *.yml*.xml

开启Metadata缓存 

被Serializer组件所使用的metadata,诸如groups,可以被缓存,以提升程序性能。任何实现了Doctrine\Common\Cache\Cache接口的服务都可以被使用。

一个利用了APCu的服务被内置在框架中:

1
2
3
4
5
# app/config/config_prod.yml
framework:
    # ...
    serializer:
        cache: serializer.mapping.cache.apc
1
2
3
4
5
<!-- app/config/config_prod.xml -->
<framework:config>
    <!-- ... -->
    <framework:serializer cache="serializer.mapping.cache.apc" />
</framework:config>
1
2
3
4
5
6
7
// app/config/config_prod.php
$container->loadFromExtension('framework', array(
    // ...
    'serializer' => array(
        'cache' => 'serializer.mapping.cache.apc',
    ),
));

开启一个命名转换器 

2.8 name_converter 选项从Symfony 2.8开始被引入。

要使用name converter服务,可以在配置文件中使用name_converter选项进行定义。

内置的CamelCase to snake_case name converter(驼峰转蛇型转换器)可以通过设置serializer.name_converter.camel_case_to_snake_case选项值来开启:

1
2
3
4
5
# app/config/config.yml
framework:
    # ...
    serializer:
        name_converter: 'serializer.name_converter.camel_case_to_snake_case'
1
2
3
4
5
<!-- app/config/config.xml -->
<framework:config>
    <!-- ... -->
    <framework:serializer name-converter="serializer.name_converter.camel_case_to_snake_case" />
</framework:config>
1
2
3
4
5
6
7
// app/config/config.php
$container->loadFromExtension('framework', array(
    // ...
    'serializer' => array(
        'name_converter' => 'serializer.name_converter.camel_case_to_snake_case,
    ),
));

深入Serializer 

ApiPlatform提供了一个API系统,它支持JSON-LDHydra Core Vocabulary hypermedia格式。它是基于Symfony框架和Serializer组件而构建的。它提供了自定义的normalizers,一个自定义的encoder,自定义的metadata以及一个缓存系统。

如果你希望利用好Symfony Serializer组件的全部威力,应该看一看这个bundle是如何工作的。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)