【问题标题】:Symfony2 JSON response returns weird UTF charactersSymfony2 JSON 响应返回奇怪的 UTF 字符
【发布时间】:2013-01-25 18:02:01
【问题描述】:

这是我的控制器方法:

  public function sendjsonAction()
  {

    $message = $this->getDoctrine()
    ->getRepository('AcmeStoreBundle:Message')
    ->findAll();
    $serializer = new Serializer(array(new GetSetMethodNormalizer()), array('message' => new 
JsonEncoder()));
    $message = $serializer->serialize($message, 'json');    
    return new JsonResponse($message);

  }

这是我的路由器:

acme_store_sendjson:
    pattern:  /sendjson/
    defaults: { _controller: AcmeStoreBundle:Default:sendjson}

这就是我去 /sendjson/ 时得到的结果:

"[{\u0022id\u0022:1,\u0022iam\u0022:1,\u0022youare\u0022:2,\u0022lat\u0022:50.8275853,\u0022lng\u0022:4.3809764,\u0022date\u0022:{\u0022lastErrors\u0022:{\u0022warning_count\u0022:0,\u0022warnings\u0022:[],\u0022error_count\u0022:0,\u0022errors\u0022:[]},\u0022timezone\u0022:{\u0022name\u0022:\u0022UTC\u0022,\u0022location\u0022:{\u0022country_code\u0022:\u0022??

(类似的情况)

我尝试使用以下内容进行 ajax 调用(使用 jQuery):

$.getJSON('/app_dev.php/sendjson', function(data) {
  var items = [];

  $.each(data, function(key, val) {
    items.push('<li id="' + key + '">' + val + '</li>');
  });

  $('<ul/>', {
    'class': 'my-new-list',
    html: items.join('')
  }).appendTo('body');
});

我得到一个

Uncaught TypeError: Cannot use 'in' operator to search for '1549' in [{"id":1,...

当我更改 Symfony2 的响应类型时,我得到一个列表

[对象] [对象] [对象] [对象] [对象] [对象] ...

我做错了什么?我应该解析答案以将 \u0022 转换为 " 还是我的响应从一开始就有错误?

编辑

我还尝试将控制器更改为:

  public function sendjsonAction()
  {
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer());
$serializer = new Serializer($normalizers, $encoders);

    $message = $this->getDoctrine()
    ->getRepository('AcmeStoreBundle:Message')
    ->findAll();
$serializer = $serializer->serialize($message, 'json');
    return new Response($serializer);
}

这次我得到了 VALID JSON,(根据 Jsonlint)但标题不是 application/json...(有意义,因为我发送的是响应而不是 JsonResponse...)(但这就是我正在尝试的避免因为 JsonResponse 似乎正在改变添加奇怪的字符)

[{"id":1,"iam":1,"youare":2,"lat":50.8275853,"lng":4.3809764,"msgbody":"I saw you over there what's up!"},{"id":2,"iam":1,"youare":2,"lat":50.8275853,"lng":4.3809764,"msgbody":"I saw you over there what's up!"},{"id":3,"iam":1,"youare":2,"lat":50.8275853,"lng":4.3809764,"msgbody":"I saw you over there what's up!"},{"id":4,"iam":1,"youare":2,"lat":50.8275853,"lng":4.3809764,"msgbody":"I saw you over there what's up!"},{"id":5,"iam":1,"youare":2,"lat":50.8275853,"lng":4.3809764,"msgbody":"I saw you over there what's up!"},{"id":6,"iam":1,"youare":2,"lat":50.8275853,"lng":4.3809764,"msgbody":"I saw you over there what's up!"}]

【问题讨论】:

  • 你的 php 看起来不错,\u0022 是一个引号。请调试您的javascript,错误应该在您的js代码中。
  • js 是正确的,直接来自 jquery.com,当我在数组中手动​​内联数据并将它们作为响应发送时它可以工作,所以问题是 json ......我不应该有引号作为 \u0022 字符..(没有 js 那里 - 那是 Symfony 的直接页面)
  • 尝试新的响应($message)。你得到了什么?
  • [{"id":1,"iam":1,"youare":2,"lat":50.8275853,"lng":4.3809764,"date":{"lastErrors":{ "warning_count":0,"warnings":[],"error_count":0 引号是正确的,但有些条目我不知道它们来自哪里,“lastErrors,warning_count,warnings,那些东西是不在我的数据库中。完全没有。getjson 调用现在给出:[object Object] [object Object] etc etc..
  • 很可能有来自序列化过程的消息。 json响应其实是一个字符串,所以在使用前尝试解析成对象stackoverflow.com/questions/45015/…

标签: json symfony unicode


【解决方案1】:

您的代码在 json 中编码两次。当您使用序列化程序自己进行 json 编码时,请使用 Response 类。

将 return new JsonResponse($message) 替换为 return new Response($message)

【讨论】:

    【解决方案2】:

    https://www.php.net/manual/en/json.constants.php

    https://www.php.net/manual/en/function.json-encode.php

    对象\Symfony\Component\HttpFoundation\JsonResponse输出JSON字符串使用函数json_encode,通过对象setEncodingOptions的方法,您可以通过JSON_UNESCAPED_UNICODE等按位常量设置输出JSON字符串选项:

    对多字节 Unicode 字符进行逐字编码(默认转义为 \uXXXX)。自 PHP 5.4.0 起可用。

    $jsonResponse = new \Symfony\Component\HttpFoundation\JsonResponse($arrayForJSON);
    $jsonResponse->setEncodingOptions($this->getEncodingOptions()|JSON_UNESCAPED_UNICODE|JSON_NUMERIC_CHECK|JSON_PRETTY_PRINT);
    $jsonResponse->send();
    

    【讨论】:

    • 仅代码的答案被认为是低质量的:请务必说明您的代码的作用以及它如何解决问题。如果您可以在帖子中添加更多信息,它将帮助提问者和未来的读者。另请参阅解释完全基于代码的答案:meta.stackexchange.com/questions/114762/…
    • 已添加到我的答案信息中。
    【解决方案3】:

    你可以只使用规范器而不使用序列化器来解决这个问题:

        $normalizer = new ObjectNormalizer();
        $array = $normalizer->normalize($newEntry);
        $entryJSONFile = json_encode($array, JSON_UNESCAPED_UNICODE);
    

    【讨论】:

      【解决方案4】:

      序列化是规范化的过程 - 创建一个表示对象的数组 - 并对该表示进行编码(即 JSON 或 XML )。 JsonResponse 会为您处理编码部分(查看类的名称),因此您不能传递“序列化对象”,否则它将再次被编码。 因此解决方案只是规范化对象并将其传递给 JsonResponse:

      public function indexAction($id)
      {
          $repository = $this->getDoctrine()->getRepository('MyBundle:Product');
          $product = $repository->find($id);
      
          $normalizer = new GetSetMethodNormalizer();
      
          $jsonResponse = new JsonResponse($normalizer->normalize($product));
          return $jsonResponse;
      }
      

      【讨论】:

        【解决方案5】:

        问题是您将字符串传递给 JsonResponse 而不是数组。

        你的控制器代码是:

        ...
        return new JsonResponse($message)
        ...
        

        您的控制器代码必须是:

        ...
        return new JsonResponse(json_decode($message, true))
        ...
        

        【讨论】:

        • 不应该真的告诉他们解码然后重新编码一些东西。这会很好地减慢它的速度。
        【解决方案6】:

        我找到了答案。

        1) 只要 JSON 有效,内容类型不是 application/json 而是 text/html 并不“真正重要”。我的 JS 没有播放的原因是我要求的是 val 而不是 val 的属性,例如 val.msgbody。 :

        所以我的 Javascript 应该是

        $.getJSON('/app_dev.php/sendjson', function(data) {
          var items = [];
        
          $.each(data, function(key, val) {
            items.push('<li id="' + key + '">' + val.msgbody + '</li>');
          });
        
          $('<ul/>', {
            'class': 'my-new-list',
            html: items.join('')
          }).appendTo('body');
        });
        

        如果 Content-Type 是必需的,那么控制器可能是这样的:

         public function sendjsonAction()
          {
            $encoders = array(new JsonEncoder());
            $normalizers = array(new GetSetMethodNormalizer());
            $serializer = new Serializer($normalizers, $encoders);
            $message = $this->getDoctrine()
              ->getRepository('AcmeStoreBundle:Message')
              ->findAll();
            $response = new Response($serializer->serialize($message, 'json')); 
            $response->headers->set('Content-Type', 'application/json');
            return $response;
          }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-08-10
          • 2018-03-13
          • 1970-01-01
          • 2019-07-05
          • 2017-07-04
          • 2018-03-11
          • 2019-07-27
          • 2016-11-08
          相关资源
          最近更新 更多