簡體   English   中英

FOSRestBundle設置返回JSON但仍然要求Twig模板

[英]FOSRestBundle setup for return JSON but still asking for Twig template

我已將FOSRestBundle配置如下:

#FOSRestBundle
fos_rest:
    param_fetcher_listener: true
    body_listener: true
    format_listener:
        rules:
            - { path: ^/, priorities: [ json, html ], fallback_format: ~, prefer_extension: true }
        media_type:
            version_regex: '/(v|version)=(?P<version>[0-9\.]+)/'

    body_converter:
        enabled: true
        validate: true

    view:
        mime_types:
            json: ['application/json', 'application/json;version=1.0', 'application/json;version=1.1']
        view_response_listener: 'force'
        formats:
            xml:  false
            json: true
        templating_formats:
            html: true

    exception:
        codes:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
            'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT
        messages:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': true
    allowed_methods_listener: true
    access_denied_listener:
        json: true

我在控制器上有這個:

namespace PDI\PDOneBundle\Controller\Rest;

use FOS\RestBundle\Controller\FOSRestController;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use FOS\RestBundle\Controller\Annotations\QueryParam;
use FOS\RestBundle\Controller\Annotations\Get;

class RepresentativeRestController extends FOSRestController
{
    /**
     * Get all representatives.
     *
     * @return array
     *
     * @ApiDoc(
     *   resource = true,
     *       https = true,
     *   description = "Get all representatives.",
     *   statusCodes = {
     *      200 = "Returned when successful",
     *      400 = "Returned when errors"
     *   }
     * )
     * @Get("/api/v1/reps")
     */
    public function getRepsAction()
    {
        $em = $this->getDoctrine()->getManager();
        $entities = $em->getRepository('PDOneBundle:Representative')->findAll();

        if(!$entities)
        {
            return $this->view(null, 400);
        }

        return $this->view($entities, 200);
    }
}

但是,當我嘗試以下URL app_dev.php/api/v1/reps出現此錯誤:

無法找到模板“”。 500內部服務器錯誤 - InvalidArgumentException 3鏈接的異常:Twig_Error_Loader»InvalidArgumentException»InvalidArgumentException»

我希望API返回一個格式良好的JSON,如下例所示:

{
   "id":"30000001",
   "veeva_rep_id":"0055648764067SwzAAE",
   "display_name":"John Know",
   "avatar_url":"http://freelanceme.net/Images/default%20profile%20picture.png",
   "rep_type":"VEEVA",
   "username":"john@mail.com",
   "first":"John",
   "last":"Know",
   "title":"Sales Representative",
   "phone":"800-555-1212",
   "email":"john@mail.com",
   "territory_id":"200454001",
   "inactive":"no",
   "total_contacts":"6",
   "total_shares":"0",
   "totalViews":"0",
   "lastLoginAt":"2015-05-05 15:45:57",
   "lastVeevaSyncAt":"2015-05-05 15:45:57",
   "createdAt":"2015-05-05 15:45:57",
   "updatedAt":"2015-05-05 15:45:57"
}

是不是為返回JSON配置了FOSRestBundle? 為什么還要求Twig模板? 我怎樣才能解決這個問題?

第一次測試:

正如@Jeet建議我嘗試使用Postman(與他告訴我的擴展名相同)並在將標題Content-Typeapplication/json ,錯誤變成了這個

格式錯誤的JSON

所以,FOSRestBundle沒有按原樣設置標頭,控制器沒有返回有效的JSON,我該如何解決這些問題呢?

第二次測試:

正如@Jeet所建議我運行這個測試:

/**
 * Get all representatives.
 *
 * @return array
 *
 * @ApiDoc(
 *   resource = true,
 *       https = true,
 *   description = "Get all representatives.",
 *   statusCodes = {
 *      200 = "Returned when successful",
 *      400 = "Returned when errors"
 *   }
 * )
 * @Get("/api/v1/reps")
 * @View()
 */
public function getRepsAction()
{
    $em = $this->getDoctrine()->getManager();
    $entities = $em->getRepository('PDOneBundle:Representative')->findAll();

    $temp = array("1", "2", "3");

    $view = $this->view($temp, Codes::HTTP_OK);
    return $this->handleView($view);
}

仍然是同一個問題:

無法找到模板“”。 500內部服務器錯誤 - InvalidArgumentException 3鏈接的異常:Twig_Error_Loader»InvalidArgumentException»InvalidArgumentException»

還有什么可能是錯的? 我在配置上遺漏了什么嗎?

我忘了首先添加app/config/routing.ymlsrc/PDI/PDOneBundle/Resources/config/routing.yml ,所以在這里,也許這是拼圖上缺少的部分,讓你更好地了解問題來自:

#app/config/routing.yml
#PDOne
pdone:
    resource: "@PDOneBundle/Resources/config/routing.yml"

template:
    resource: "@TemplateBundle/Resources/config/routing.yml"

#FOSUserBundle
fos_user:
    resource: "@FOSUserBundle/Resources/config/routing/all.xml"
    prefix: /

#NelmioApiDocBundle:
NelmioApiDocBundle:
    resource: "@NelmioApiDocBundle/Resources/config/routing.yml"
    prefix:   /api/doc

#SonataAdmin
admin:
    resource: '@SonataAdminBundle/Resources/config/routing/sonata_admin.xml'
    prefix: /admin

_sonata_admin:
    resource: .
    type: sonata_admin
    prefix: /admin

#src/PDI/PDOneBundle/Resources/config/routing.yml
pdone:
    resource: "@PDOneBundle/Controller/"
    type:     annotation
    prefix:   /

第三次測試:

對於客戶端的請求肯定有問題,如果我使用像Postman這樣的工具並設置正確的標題,我可以按照自己的意願獲得實體,請參見下圖:

在此輸入圖像描述

我無法找到問題所在,所以我迫切需要別人的幫助,因為我已經沒有想法了

正如大家建議的那樣:只有Accept標頭或擴展名可以給你一個JSON。 好像你已經用Accept標頭對它進行了排序。

為了使用擴展,你必須告訴你如何在Symfony中設置格式。

此代碼應該為您提供所需的輸出:

namespace RestTestBundle\Controller;

use FOS\RestBundle\Controller\Annotations\View;

use FOS\RestBundle\Controller\Annotations\Get;

class YourController
{
    /**
     * @Get("/api/v1/reps.{_format}", defaults={"_format"="json"})
     * @View()
     */
    public function indexAction()
    {
        return array(
            'status' => 'ok',
            'companies' => array(
                array('id' => 5),
                array('id' => 7),
            ),
        );
    }
}

Edit1:如果你不想使用View類,而是純數組:別忘了禁止對SensioExtraBundle的View處理

sensio_framework_extra:
    view:    { annotations: false }

Edit2:如果你不使用HTML格式並且只想擁有一個json輸出,你可以使用這樣的配置:

fos_rest:
    # ....
    format_listener:
        rules:
            - { path: ^/, priorities: [ json ], fallback_format: json, prefer_extension: true }
    # ....

解釋為什么您看到錯誤“未找到視圖”:

TL; DR:您的瀏覽器發送一個Accept標頭,告訴FOSRestBundle輸出'html'變體。

背景:此捆綁包主要使用Accept頭,這是一個很好的做法,可以使用所有可用的輸出格式:html(您可以使用您提供的表單測試REST API,對象列表,對象的詳細信息),json ,xml。 有時甚至圖像mime類型如image / jpeg,image / png作為默認值或json / xml作為變體(您可以使用base64圖像表示)。

說明:如果打開瀏覽器的“網絡”選項卡並查看它發送的標題,您會注意到: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8表示“按此順序使用”:

  1. text / html的
  2. 應用/ XHTML + xml的
  3. application / xml ,優先級為0.9 ,根據您的配置禁止
  4. * / *優先級為0.8 ,以及任何格式

如果您仔細觀察,您會看到根據您的配置文本/ html是您的配​​置變體之一('html')和* / *是另一個變體('json'),但text / html有一個變體優先級為1,而* / *的優先級為0.8,因此text / html匹配,FOSRestBundle嘗試查找HTML表示並失敗。

PS:如果你多次發帖 - 請確保你注意每個帖子中的所有回復。

您可以通過兩種方式給出回復

return View::create($entities, Codes::HTTP_OK);

要么

$view = $this->view($entities, Codes::HTTP_OK);    
return $this->handleView($view)

FosRestBundle利用Accept Header。 這意味着它會根據您的請求返回響應。 通過訪問路徑“app_dev.php / api / v1 / reps”,您隱式請求html格式,因此它嘗試提供模板。

app_dev.php / api / v1 / reps.json會返回您需要的內容嗎?

您還應該測試app_dev.php / api / v1 / reps.xml並期望輸出xml

你可以簡單地使用

            $view = new View($form);
            $view->setFormat('json');
            return $this->handleView($view);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM