【问题标题】:Return a JSON array from a Controller in Symfony从 Symfony 中的控制器返回 JSON 数组
【发布时间】:2015-03-24 08:08:07
【问题描述】:

我正在尝试从 Symfony 2 中的控制器返回 JSON 响应。例如,在 Spring MVC 中,我可以使用 @ResponseBody 注释获得 JSON 响应。我想得到一个 JSON 响应,不管它是 JSON 数组还是 Json 对象,然后在视图中使用 javascript 操作它。

我尝试下一个代码:

/**
     * @Route(
     *      "/drop/getCategory/",
     *      name="getCategory"
     * )
     * @Method("GET")
     */
    public function getAllCategoryAction() {
        $categorias = $this->getDoctrine()
                           ->getRepository('AppBundle:Categoria')
                           ->findAll();

        $response = new JsonResponse();
        $response->setData($categorias);

        $response->headers->set('Content-Type', 'application/json');
        return $response;
    }

但我在浏览器中得到[{},{}] 作为响应。我也尝试使用$response = new Response(json_encode($categorias));,但我得到了相同的结果。

【问题讨论】:

  • 你试过'return new JSONResponse($data);'吗?

标签: php json symfony


【解决方案1】:

我认为@darkangelo 的答案需要解释。

findAll() 方法返回一个对象集合。

$categorias = $this->getDoctrine()
                   ->getRepository('AppBundle:Categoria')
                   ->findAll();

要构建响应,您必须将实体的所有 getter 添加到响应中,例如:

$arrayCollection = array();

foreach($categorias as $item) {
     $arrayCollection[] = array(
         'id' => $item->getId(),
         // ... Same for each property you want
     );
}

return new JsonResponse($arrayCollection);

使用QueryBuilder 允许您将结果作为包含所有属性的数组返回:

$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
    'SELECT c
    FROM AppBundle:Categoria c'
);
$categorias = $query->getArrayResult();

return new JsonResponse($categorias);

getArrayResult() 避免了对 getter 的需要。

【讨论】:

    【解决方案2】:

    您需要这样做(基于之前的答案):

    public function getAllCategoryAction() {
        $em = $this->getDoctrine()->getManager();
        $query = $em->createQuery(
            'SELECT c
            FROM AppBundle:Categoria c'
        );
        $categorias = $query->getArrayResult();
    
        $response = new Response(json_encode($categorias));
        $response->headers->set('Content-Type', 'application/json');
    
        return $response;
    }
    

    它适用于 Doctrine 作为数组返回的任何查询。

    【讨论】:

    • 您可以使用JsonResponse 而不是Response 来改进您的答案。这将避免重复使用 json_encode 和自定义标头。
    【解决方案3】:
    /**
     * @Route("/api/list", name="list")
     */
    public function getList(SerializerInterface $serializer, SomeRepository $repo): JsonResponse
    {
        $models = $repo->findAll();
        $data = $serializer->serialize($models, JsonEncoder::FORMAT);
        return new JsonResponse($data, Response::HTTP_OK, [], true);
    }
    

    【讨论】:

      【解决方案4】:

      您需要以这种方式更改您的代码:

      /**
       * @Route(
       *      "/drop/getCategory/",
       *      name="getCategory"
       * )
       * @Method("GET")
       */
      public function getAllCategoryAction() {
          $categorias = $this->getDoctrine()
                             ->getRepository('AppBundle:Categoria')
                             ->findAll();
      
          $categorias = $this->get('serializer')->serialize($categorias, 'json');
      
          $response = new Response($categorias);
      
          $response->headers->set('Content-Type', 'application/json');
          return $response;
      }
      

      如果serializer服务没有开启,你必须在app/config/config.yml开启:

          framework:
              # ...
              serializer:
                  enabled: true
      

      更高级的序列化选项,可以安装JMSSerializerBundle

      【讨论】:

      • 我收到 500 错误:您请求了一个不存在的服务“序列化程序”。
      • 您必须先启用序列化程序服务。在 app/config/config.yml 添加这个:framework: # ... serializer: enabled: true
      • 我得到了解决方案:$categorias = $query->getArrayResult(); //$response->headers->set('Content-Type', 'application/json'); //返回$响应; //return $this->render('AppBundle:Front:test.html.twig', array('otra' => $otra)); return new Response(json_encode($categorias), 200);
      • 这也是一个很好的解决方案。没有使用serializer 服务?我发现使用序列化程序是一种更好的做法
      【解决方案5】:

      看起来您正试图响应一个集合。为此,您需要设置序列化程序(或将数据作为数组检索)。

      查看此文档页面:http://symfony.com/doc/current/components/http_foundation/introduction.html#creating-a-json-response

      http://symfony.com/doc/current/cookbook/serializer.html.

      【讨论】:

        【解决方案6】:

        按照最佳实践,我设法做到了以下方式:

        public function index(CityRepository $cityRepository,
                              SerializerInterface $serializer): Response 
        

        注入存储库和序列化程序。

        $cities = $cityRepository->findAll();
        

        检索对象数组。

        $data = $serializer->serialize($cities, 'json');
        

        将数据序列化为 JSON 字符串。

        return new JsonResponse($data, 200, [], true);
        

        将 JSON 字符串传递给 JsonResponse

        【讨论】:

        • 我得到了非常丑陋的对象 "{\u0022id\u0022:105,\u0022name\u0022:\u00223..." 如何解决?
        • @ArturO 这个例子中的序列化器返回一个 JSON 字符串;检查JsonResponse 的最后一个参数是否设置为true。
        【解决方案7】:

        我建议以下解决方案:

        /**
             * @Route(
             *      "/drop/getCategory/",
             *      name="getCategory"
             * )
             * @Method("GET")
             */
            public function getAllCategoryAction() {
                $em = $this->getDoctrine()->getManager();
                $query = $em->createQuery(
                    'SELECT c
                    FROM AppBundle:Categoria c'
                );
                $categorias = $query->getArrayResult();
        
        
                return new Response(json_encode($categorias), 200);
        }
        

        【讨论】:

        • 您可能应该像在问题中那样使用 newJsonResponse。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多