Skip to content

Parsing API Parameters

EK edited this page Sep 23, 2015 · 9 revisions

JSON API clients should send data to servers

  • As URL parameters
  • In HTTP headers
  • In HTTP body

The server should parse those data, check them and act accordingly. This package provides a few helpers that simplify these tasks.

URL and Header Parameters

Application may use the following parameters in URL

The package provides parser for these parameters which returns ParametersInterface (description below) which is used for checking validity of input parameters and in application logic (data fetching from database, sorting, filtering, etc).

The parser is intended to be integrated with application/framework once and used seamlessly. For integration samples see package tests or framework integrations code.

In real application 'parsing' and 'parameters validation' might be just one line

class SomeController extends Controller
{
    ...

	public function show($id)
	{
        /** @var ParametersInterface $parameters */
        $parameters = $this->getParameters();
        
        ...
    }
    
    ...
}

Sorry the quoting a few interfaces below. The next section gives some information on 'parameters validation'.

interface ParametersInterface extends EncodingParametersInterface
{
    /**
     * Get get 'Content-Type' header.
     *
     * @return HeaderInterface
     */
    public function getContentTypeHeader();

    /**
     * Get 'Accept' header.
     *
     * @return AcceptHeaderInterface
     */
    public function getAcceptHeader();

    /**
     * Get sort parameters.
     *
     * @return SortParameterInterface[]|null
     */
    public function getSortParameters();

    /**
     * Get pagination parameters.
     *
     * Pagination parameters are not detailed in the specification however
     * a keyword 'page' is reserved for pagination.
     * This method returns key and value pairs from input 'page' parameter.
     *
     * @return array|null
     */
    public function getPaginationParameters();

    /**
     * Get filtering parameters.
     *
     * Filtering parameters are not detailed in the specification however
     * a keyword 'filter' is reserved for filtering.
     * This method returns key and value pairs from input
     * 'filter' parameter.
     *
     * @return array|null
     */
    public function getFilteringParameters();

    /**
     * Get top level parameters that have not been recognized by parser.
     *
     * @return array|null
     */
    public function getUnrecognizedParameters();
}

interface HeaderInterface
{
    /**
     * Get header name.
     *
     * @return string
     */
    public function getName();

    /**
     * Get media types.
     *
     * @return MediaTypeInterface[]
     */
    public function getMediaTypes();
}

interface AcceptHeaderInterface extends HeaderInterface
{
    /**
     * Get sorted/ranged media types (by quality factor, type,
     * subtype and extensions).
     *
     * @return AcceptMediaTypeInterface[]
     */
    public function getMediaTypes();
}

interface MediaTypeInterface
{
    /**
     * Get media type (no subtype).
     *
     * @return string
     */
    public function getType();

    /**
     * Get media subtype.
     *
     * @return string
     */
    public function getSubType();

    /**
     * Get full media type (type/subtype).
     *
     * @return string
     */
    public function getMediaType();

    /**
     * Get media type parameters.
     *
     * @return array<string,string>|null
     */
    public function getParameters();

    /**
     * Compare media types.
     *
     * @param MediaTypeInterface $mediaType
     *
     * @return bool
     */
    public function matchesTo(MediaTypeInterface $mediaType);

    /**
     * Compare media types.
     *
     * @param MediaTypeInterface $mediaType
     *
     * @return bool
     */
    public function equalsTo(MediaTypeInterface $mediaType);
}

interface AcceptMediaTypeInterface extends MediaTypeInterface
{
    /**
     * Get quality factor.
     *
     * @return float Quality factor [0 .. 1]
     */
    public function getQuality();

    /**
     * Get media type extension parameters.
     *
     * @return array<string,string>|null
     */
    public function getExtensions();

    /**
     * Get initial position of the media type in header
     * (needed for stable sorting).
     *
     * @return int
     */
    public function getPosition();
}

Parameters Validation

Applications should check input parameters which might require a lot similar of code in every method. This package provides a helper class RestrictiveParameterChecker that make this task much easier.

In real application Controller class might have class fields that configure

  • a list of allowed include paths.
  • a list of allowed sparse fieldsets.
  • a list of allowed paging, filtering and sorting parameters.

In real application assuming base class has reasonable default values customized usage might looks like

class SomeController extends Controller
{
    ...

    /**
     * A list of allowed include paths in input parameters.
     *
     * Empty array [] means clients are not allowed to specify
     * include paths and 'null' means all paths are allowed.
     *
     * @var string[]|null
     */
    protected $allowedIncludePaths = [
        'posts.author',
    ];

	public function show($id)
	{
        /** @var ParametersInterface $parameters */
        $parameters = $this->getParameters();
        
        ...
    }
    
    ...
}

Input headers and parameters will be validated automatically

on $this->getParameters() invoke.

RestrictiveParameterChecker is intended to be integrated with application/framework once and used seamlessly. For integration samples see package tests or framework integrations code.

Header parsers

As the spec says

Clients MUST indicate that they can accept the JSON API media type, per the semantics of the HTTP Accept header.

which basically means JSON API server must handle those headers in accordance with RFC 2616. That's an example of a header that servers must support

Accept: application/vnd.api+json;q=0.5,text/html;q=0.8;*/*;q=0.1

Note: the package supports media type parameters and extensions as well. Specification reserves 'ext' parameter for future use and do not use media type extensions.

And server may choose to support text/html in order to simplify viewing content via a web browser.

There are 2 methods for parsing HTTP headers

  • AcceptHeader::parse(string $header) for Accept header.
  • Header::parse(string $header, string $headerName) for other headers e.g. Content-Type header.

These classes are intended to be integrated with frameworks and its usage is seamless to applications. Typically they are not used directly by applications. If you are interested in technical details see framework integrations page.

HTML body parser

The package does not contain any decoders for request body as it usually has relatively simple structure and is application specific thus json_decode works fine in many cases.

However the package has code that integrates such vital application parts as

  • Headers decoding.
  • Parameters decoding.
  • Support for multiple encoder and decoder formats.
  • Matching encoders and decoders to input/output media types as requested in headers.
  • Parameters validation.
  • Output encoding.
  • Preparing HTTP responses.
  • Exception handling and exception to JSON API errors conversion.

For integration samples see framework integrations samples.