-
Notifications
You must be signed in to change notification settings - Fork 66
Home
Via Composer
$ composer require neomerx/json-api ~0.6.0
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).
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
andrelated
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
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
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.
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);
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 inLink
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 inEncodingParametersInterface
. This feature allows users to specify desired include paths in HTTP requests. For additional information see Parsing API Parameters section.
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).
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"}
}]
}