Skip to content
EK edited this page Dec 3, 2015 · 20 revisions

Install

Via Composer

$ composer require neomerx/json-api ~0.6.0

JSON API Encoder Usage

In order to encode an arbitrary resource object to JSON API format there are 3 main steps

  • Create a Schema for the resource and resources it references.
  • Create an Encoder instance.
  • Encode resource(s), links, meta information or error(s).

Schemas

A Schema is a class that inherits SchemaProvider and provides information on how an arbitrary resource object(s) (class, Model, etc) should be converted to JSON API format. It gives

  • Information about resource attributes.
  • Information about resource relationships to other resources.
  • Resource id, JSON API type and URL.
  • Conversion settings (e.g. if self and related URLs should be shown, if meta information should be shown, etc).
  • Information what relationships should be placed to included section for each resource type independently.
  • Relationship pagination links.

For more details please check out the Schemas section

Encoder Instance

Encoder class has a static method instance

    /**
     * Create encoder instance.
     *
     * @param array               $schemas       Schema providers.
     * @param EncoderOptions|null $encodeOptions
     *
     * @return Encoder
     */
    public static function instance(
        array $schemas,
        EncoderOptions $encodeOptions = null
    )

which accepts an array of mapping between resource types and resource schemas

$encoder = Encoder::instance([
    // class names as strings
    '\Author'      => '\AuthorSchema',
    // '::class' constant (PHP 5.5+) convenient for classes in namespaces
    Comment::class => CommentSchema::class, 
    Post::class    => PostSchema::class,
    Site::class    => SiteSchema::class
], new EncoderOptions(JSON_PRETTY_PRINT));

Typically Schema mapping is stored in an external configuration file.

It is worth mentioning that the mapping supports advanced usage with Closure. Instead of schema class name you can specify Closure which will be invoked on schema creation. This feature could be used for setting up schemas based on configuration settings, environment variables, user input and etc.

Sample usage

$schemaClosure = function ($factory, $container) {
    $schema = new CommentSchema($factory, $container, ..., ..., ...);
    return $schema;
};

$encoder = Encoder::instance([
    Author::class  => AuthorSchema::class,
    Comment::class => $schemaClosure,
]);

EncoderOptions

EncoderOptions is an auxiliary class that is used for setting such options as

  • Json encoding options.
  • Optional prefix that could be applied to Links in the document.

EncoderOptions has a constructor

/**
 * @param int         $options
 * @param string|null $urlPrefix
 * @param int         $depth
 */
public function __construct(
    $options = 0,
    $urlPrefix = null,
    $depth = 512
);

$options and $depth are parameters for json_encode. Parameter $options has predefined values described in official PHP documentation.

$urlPrefix sets document Links prefix. You can convert all relative URLs (e.g. /authors) to full URLs (e.g. http://example.com/authors) with methods such as Request::getSchemeAndHttpHost or similar.

Encode

Encoder has a few methods for data conversion

    /**
     * Encode input as JSON API string.
     *
     * @param object|array|Iterator|null       $data       Data to encode.
     * @param EncodingParametersInterface|null $parameters Encoding params.
     *
     * Sample usage
     *
     *     $encoder->withLinks([...])->withMeta(...)->encodeData($data);
     *
     * @return string
     */
    public function encodeData(
        $data,
        EncodingParametersInterface $parameters = null
    );

    /**
     * Add links that will be encoded with data.
     * Links must be in array<string,LinkInterface> format.
     *
     * @param array $links Links information(e.g. request URL or paging)
     *
     * @return EncoderInterface
     */
    public function withLinks(array $links);

    /**
     * Add meta information that will be encoded with data.
     * If `null` meta will not appear in a document.
     *
     * @param mixed|null $meta
     *
     * @return EncoderInterface
     */
    public function withMeta($meta);

    /**
     * If called JSON API version information with optional
     * meta will be added to a document.
     *
     * @param mixed|null $meta
     *
     * @return EncoderInterface
     *
     * @see http://jsonapi.org/format/#document-jsonapi-object
     */
    public function withJsonApiVersion($meta = null);

    /**
     * Add 'self' Link to top-level document's 'links' section
     * for relationship specified.
     *
     * @param object     $resource
     * @param string     $relationshipName
     * @param null|mixed $meta
     * @param bool       $treatAsHref
     *
     * @see http://jsonapi.org/format/#fetching-relationships
     *
     * @return EncoderInterface
     */
    public function withRelationshipSelfLink(
        $resource,
        $relationshipName,
        $meta = null,
        $treatAsHref = false
    );

    /**
     * Add 'related' Link to top-level document's 'links' section
     * for relationship specified.
     *
     * @param object     $resource
     * @param string     $relationshipName
     * @param null|mixed $meta
     * @param bool       $treatAsHref
     *
     * @see http://jsonapi.org/format/#fetching-relationships
     *
     * @return EncoderInterface
     */
    public function withRelationshipRelatedLink(
        $resource,
        $relationshipName,
        $meta = null,
        $treatAsHref = false
    );

    /**
     * Encode input as JSON API string with a list of resource identifiers.
     *
     * @param object|array|Iterator|null       $data       Data to encode.
     * @param EncodingParametersInterface|null $parameters Encoding parameters.
     *
     * @return string
     */
    public function encodeIdentifiers(
        $data,
        EncodingParametersInterface $parameters = null
    );

    /**
     * Encode input meta as JSON API string.
     *
     * @param array|object $meta Meta information.
     *
     * @return string
     */
    public function encodeMeta($meta);

    /**
     * Encode error as JSON API string.
     *
     * @param ErrorInterface $error
     *
     * @return string
     */
    public function encodeError(ErrorInterface $error);

    /**
     * Encode errors as JSON API string.
     *
     * @param ErrorInterface[] $errors
     *
     * @return string
     */
    public function encodeErrors($errors);

Encoding

The encode method accepts an object or and array of objects and requires Schemas for those objects and their relationships.

$links is an optional parameter that could be used to specify JSON API top-level links section.

$meta is an optional parameter that could be used to specify JSON API top-level meta section. This parameter could be any type that json_encode can work with (e.g. string, array, etc).

Usage example

$links = [
    'custom-link' => new Link('http://example.com/custom/link', null, true),
];
$meta  = [
    'copyright' => "Copyright 2015 Example Corp.",
    'authors'   => [
        'Yehuda Katz',
        'Steve Klabnik',
        'Dan Gebhardt'
    ]
];

Encoder::instance([
    Author::class => AuthorSchema::class
])->withLinks($links)->withMeta($meta)->encodeData($author);

Sample result

{
    "meta" : {
        "copyright" : "Copyright 2015 Example Corp.",
        "authors" : [
            "Yehuda Katz",
            "Steve Klabnik",
            "Dan Gebhardt"
        ]
    },
    "links" : {
        "custom-link" : "http://example.com/custom/link"
    },
    "data" : {
        "type" : "people",
        "id"   : "9",
        "attributes" : {
            "first_name" : "Dan",
            "last_name"  : "Gebhardt"
        },
        "links" : {
            "self" : "/people/9"
        }
    }
}

Note: links like self, related, paging links and others are usually encoded as plain string URLs. However the specification says they could have meta information. If so the second parameter in Link class specifies link meta e.g. new Link('/some-url', ['some' => 'meta']). An example of such link could be found in the spec Links section.

EncodingParametersInterface is an optional parameter that could be used for filtering output. It implements JSON API Sparse Fieldsets and Inclusion of Related Resources features.

Usage example

$options  = new EncodingParameters(
    ['posts.author'], // Paths to be included
    [
        // Attributes and links that should be filtered
        'sites'  => ['name'],
        'people' => ['first_name'],
    ]
);
$encoder  = Encoder::instance([
    Author::class  => AuthorSchema::class,
    Comment::class => CommentSchema::class,
    Post::class    => PostSchema::class,
    Site::class    => SiteSchema::class
], new EncoderOptions(JSON_PRETTY_PRINT));

Note: default include paths defined in Schema could be overwritten with include paths defined in EncodingParametersInterface. This feature allows users to specify desired include paths in HTTP requests. For additional information see Parsing API Parameters section.

encodeMeta method

For certain cases a response with only meta information should be sent back to clients. This method provides such ability.

Input parameter $meta could be any type that json_encode can work with (e.g. string, array, etc).

Error methods

Encoder supports encoding JSON API Error objects.

Usage example

$error = new Error(
    'some-id',
    new Link('about-link'),
    'some-status',
    'some-code',
    'some-title',
    'some-detail',
    ['source' => 'data'],
    ['some'   => 'meta']
);

Encoder::instance([])->encodeError($error);

Sample result

{
    "errors":[{
        "id"     : "some-id",
        "links"  : {"about" : "about-link"},
        "status" : "some-status",
        "code"   : "some-code",
        "title"  : "some-title",
        "detail" : "some-detail",
        "source" : {"source" : "data"},
        "meta"   : {"some" : "meta"}
    }]
}
Clone this wiki locally