【问题标题】:How to pass options to json_encode function in Symfony Serializer component如何将选项传递给 Symfony Serializer 组件中的 json_encode 函数
【发布时间】:2016-12-13 11:57:12
【问题描述】:

情况是这样的:我在一个基于symfony3的rest api上工作,它使用FOSRestBundle和symfony序列化组件,所以方法返回数组,FOSRest处理编码和响应。问题是序列化程序使用带有默认设置的 json_encode 和 api 返回数据,例如某些符号的 '\u00c9S'。所以我需要以某种方式将 'JSON_UNESCAPED_UNICODE' 传递给 json_encode() 。有没有合适的方法来达到这个目标? 方法示例:

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use FOS\RestBundle\Controller\Annotations as Rest;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class ExampleController
 * @package AppBundle\Controller
 */
class ExampleController extends Controller
{
    /**
     * @Rest\Get("/get-some-data")
     * @param Request $request
     * @return array
     */
    public function getSomeDataAction(Request $request)
    {
        $someData = [
            'prop1' => 'Value',
            'prop2' => 'Value',
            'prop3' => 'Value',
            'prop4' => 'Value',
        ];

        return $someData;
    }

所以当我请求“/get-some-data”时,它会返回给我:

{"prop1":"Value with \/","prop2":"Value with \u00c9"}

,但我需要它返回:

{"prop1":"Value with /","prop2":"Value with É"} 

【问题讨论】:

    标签: php symfony fosrestbundle serialization


    【解决方案1】:

    我使用 Symfony 3 和“Doctrine JSON ODM Bundle”将我的数据存储为 JSON 文档。我有同样的问题。所有包含 unicode 字符的数据都会自动转义,这不是我想要的。

    经过一些实验,我终于设法将JSON_UNESCAPED_UNICODE 选项传递给json_encode()。 以下是我的解决方案:

    # config/services.yml
    
        serializer.encode.json.unescaped:
            class: Symfony\Component\Serializer\Encoder\JsonEncode
            arguments:
               - !php/const JSON_UNESCAPED_UNICODE
    
        serializer.encoder.json:
            class: Symfony\Component\Serializer\Encoder\JsonEncoder
            arguments:
                - '@serializer.encode.json.unescaped'
    

    【讨论】:

      【解决方案2】:

      Symfony 5 的解决方案。

      从 Symfony 4.2 起,不推荐将整数作为“Symfony\Component\Serializer\Encoder\JsonEncode::__construct()”方法的第一个参数传递,而是使用上下文的“json_encode_options”键。

      添加到 config/services.yaml:

      serializer.encode.json.unescaped:
          class: Symfony\Component\Serializer\Encoder\JsonEncode
          arguments:
              - { "json_encode_options": !php/const JSON_UNESCAPED_UNICODE }
      
      serializer.encoder.json:
          class: Symfony\Component\Serializer\Encoder\JsonEncoder
          arguments:
              - '@serializer.encode.json.unescaped'
      

      【讨论】:

        【解决方案3】:

        当在原则中为列设置 json 类型时,后台使用 PHP 的 json_encode() 和 json_decode() 函数来存储和检索数据库中的数据。

        json_encode() 将 PHP 的数组转换为 JSON 字符串的函数有第二个参数,用于指定设置一些转换规则的选项集。其中之一是 JSON_UNESCAPED_UNICODE,它禁用将多字节符号编码为 \uXXXX

        默认情况下,我们可以为 json_encode() 启用此选项。要利用它,您必须执行 2 个步骤。

        1.创建类 App\Doctrine\Types\JsonType

        // App\Doctrine\Types\JsonType.php
        
        <?php
        
        namespace App\Doctrine\Types;
        use Doctrine\DBAL\Platforms\AbstractPlatform;
        
        
        class JsonType extends \Doctrine\DBAL\Types\JsonType
        {
        
            public function convertToDatabaseValue($value, AbstractPlatform $platform)
            {
                if ($value === null) {
                    return null;
                }
        
                $encoded = json_encode($value, JSON_UNESCAPED_UNICODE);
        
                if (json_last_error() !== JSON_ERROR_NONE) {
                    throw ConversionException::conversionFailedSerialization($value, 'json', json_last_error_msg());
                }
        
                return $encoded;
            }
        
        }
        

        2。覆盖与我们的类对应的 DBAL JSON 类型的配置

        # config/packages/doctrine.yaml
        doctrine:
            dbal:
                types:
                    json: App\Doctrine\Types\JsonType
        

        【讨论】:

        【解决方案4】:

        您可以使用heredocumentation 中的编码器

        <?php
        $encoder = new JsonEncoder(new JsonEncode(JSON_UNESCAPED_UNICODE), new JsonDecode(false));
        $normalizer = new ObjectNormalizer();
        $serializer = new Serializer(array($normalizer), array($encoder));
        

        编辑:

        在这个例子中,我使用了一个 Response 对象。请注意,动作控制器必须返回 Response 对象。

        namespace AppBundle\Controller;
        
        use Symfony\Bundle\FrameworkBundle\Controller\Controller;
        use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
        use FOS\RestBundle\Controller\Annotations as Rest;
        use Nelmio\ApiDocBundle\Annotation\ApiDoc;
        use Symfony\Component\HttpFoundation\Request;
        
        /**
         * Class ExampleController
         * @package AppBundle\Controller
         */
        class ExampleController extends Controller
        {
            /**
             * @Rest\Get("/get-some-data")
             * @param Request $request
             * @return array
             */
            public function getSomeDataAction(Request $request)
            {
                $someData = [
                    'prop1' => 'Value',
                    'prop2' => 'Value',
                    'prop3' => 'Value',
                    'prop4' => 'Value',
                ];
                $response = new Response($someData);
                $response->headers->set('Content-Type', 'application/json');
                return $response;
            }
        

        【讨论】:

        • 我没听懂。我不参与序列化过程,FOSRestBundle 处理它。我应该扩展一些课程吗?
        • 你能举个例子吗?我会尽量适应我自己的。我的代码只使用 Symfony 序列化器组件。
        • 在问题中添加示例。
        • 你有对象,还是直接json字符串?
        • 作为响应,我有一个 json 字符串。
        【解决方案5】:

        在较新版本的 symfony 中,您必须使用这种格式:

        $encoders = [new JsonEncoder(new JsonEncode(["json_encode_options" => 
        JSON_UNESCAPED_SLASHES]), new JsonDecode([]))];
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-11-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-13
          • 1970-01-01
          • 2013-03-06
          • 1970-01-01
          相关资源
          最近更新 更多