简体   繁体   中英

How to return or display data in JSON format using FOSRestBundle

I am working in a Restful API using Symfony2 and FOSRestBundle. I have read view layer docs but is not clear to me how to handle output for API. What I want to achieve is simple: display or return or output the result as valid JSON. This is what I have at controller:

<?php

/**
 * RestAPI:       Company.
 */
namespace PDI\PDOneBundle\Controller\Rest;

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

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

        if ($entities) {
            foreach ($entities as $entity) {
                $response['companies'][] = [
                    'id' => $entity->getId(),
                    'createdAt' => $entity->getCreatedAt(),
                    'updatedAt' => $entity->getUpdatedAt(),
                    'name' => $entity->getName(),
                    'logo_url' => $entity->getLogoUrl(),
                    'division' => $entity->getDivision(),
                    'inactive' => $entity->getInactive(),
                ];
            }

            $response['status'] = 'ok';
        } else {
            $response['status'] = 'error';
        }

        return $response;
    }
}

If I try this URL: /app_dev.php/api/v1/companies.json I got 404 error:

{"code":404,"message":"No route found for \"GET\/api\/v1\/companies.json\""}

If I try this URL: https://reptool.dev/app_dev.php/api/v1/companies error turns on:

Unable to find template "". 500 Internal Server Error - InvalidArgumentException 3 linked Exceptions: Twig_Error_Loader » InvalidArgumentException » InvalidArgumentException »

I've also check FOSRestBundleByExample but didn't get much help.

What I am missing here? How do I achieve what I need? Any advice?

FOSRest Config

I forgot to add the FOSRestBundle at config.yml :

#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

I feel your pain. I had troubles getting started as well. One important place to start is the config. Here's what I use in my implementation.

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

In the format_listener if you want JSON to be the default response, make sure it's set first in priorities. Otherwise your header will need to include Accept: application/json every time. This may be why you're getting a twig error as it's trying to use twig to render an HTML output.

Also, make sure you have a serializer like http://jmsyst.com/bundles/JMSSerializerBundle installed and included in your AppKernal.

In your controller I found it easiest to extend the FOSRestController like you did, but also return a view object instead of creating the array yourself. The serializer will handle all of that for you.

/**
 * RestAPI:       Company.
 */
namespace PDI\PDOneBundle\Controller\Rest;

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

class CompanyRestController extends FOSRestController
{
    /**
     * Gets all companies.
     *
     * @return array
     *
     * @ApiDoc(
     *   resource = true,
     *       https = true,
     *   description = "Gets all companies",
     *   statusCodes = {
     *      200 = "Returned when successful",
     *      400 = "Returned when errors"
     *   }
     * )
     * @Get("/api/v1/companies")
     *
     */
    public function getCompaniesAction()
    {
        $response = array();
        $em = $this->getDoctrine()->getManager();
        $entities = $em->getRepository('PDOneBundle:Company')->findAll();
        if(!$entities)
        {
             return $this->view(null, 400);
        }

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

I hope this helps a little.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM