juliangut / json-api
PSR7 aware json-api integration
Fund package maintenance!
juliangut
Installs: 2 003
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 3
Forks: 0
Open Issues: 3
Requires
- php: ^8.0
- ext-json: *
- juliangut/mapping: ^1.4.2
- laravel-json-api/neomerx-json-api: ^5.0.2
- psr/http-message: ^1.0|^2.0
- psr/http-server-middleware: ^1.0
- symfony/polyfill-php81: ^1.27
Requires (Dev)
- ext-dom: *
- ext-json: *
- doctrine/annotations: ^2.0
- infection/infection: ~0.25|~0.27
- juliangut/easy-coding-standard-config: ^1.15
- juliangut/phpstan-config: ^1.2
- laminas/laminas-diactoros: ^3.2
- overtrue/phplint: ^9.0
- phpcompatibility/php-compatibility: ^9.3
- phpmd/phpmd: ^2.15
- phpunit/phpunit: ^9.6|^10.4
- povils/phpmnd: ^3.2
- roave/security-advisories: dev-master
- symfony/console: ^6.0
- symfony/yaml: ^6.0
Suggests
- symfony/console: In order to use console commands (>=5.1)
- symfony/yaml: In order to load resource mapping from YAML files (>=5.1)
This package is auto-updated.
Last update: 2024-12-15 18:00:59 UTC
README
json-api
Easy JSON:API integration.
Installation
Composer
composer require juliangut/json-api
symfony/yaml to parse yaml files
composer require symfony/yaml
Usage
Require composer autoload file
require './vendor/autoload.php';
use Jgut\JsonApi\Manager; use Jgut\JsonApi\Configuration; use Neomerx\JsonApi\Schema\Error; $configuration = new Configuration([ 'sources' => ['/path/to/resource/files'], ]); $jsonApiManager = new Manager($configuration); // Get encoded errors $jsonApiManager->encodeErrors(new Error()); // Get encoded resources $jsonApiManager->encodeResources(new MyClass(), new ServerRequestInstance());
Configuration
sources
must be an array containing arrays of configurations to create MappingDriver objects:type
one of \Jgut\JsonApi\Mapping\Driver\DriverFactory constants:DRIVER_ATTRIBUTE
,DRIVER_PHP
,DRIVER_JSON
,DRIVER_XML
,DRIVER_YAML
orDRIVER_ANNOTATION
if no driver, defaults to DRIVER_ATTRIBUTEpath
a string path or array of paths to where mapping files are located (files or directories) REQUIRED if no driverdriver
an already created \Jgut\JsonApi\Mapping\Driver\DriverInterface object REQUIRED if no type AND path
attributeName
name of the PSR-7 Request attribute that will hold query parameters for resource encoding, defaults to 'JSON_API_query_parameters'schema
class name implementing \Jgut\JsonApi\Schema\MetadataSchemaInterface (\Jgut\JsonApi\Schema\MetadataSchema by default)prefix
prefix for generated URLsmetadataResolver
an instance of \Jgut\Mapping\Metadata\MetadataResolver. It is highly recommended to provide a PSR-16 cache to metadata resolver on productionencodingOptions
global encoding options, an instance of \Jgut\JsonApi\Encoding\OptionsInterfacejsonApiVersion
none by defaultjsonApiMeta
optional global metadata
Middleware
Use PSR-15 middleware Jgut\JsonApi\Middleware\JsonApiMiddleware
in order to validate request being a valid JSON:API specification request
use Jgut\JsonApi\Manager; use Jgut\JsonApi\Middleware\JsonApiMiddleware; use Psr\Http\Message\ResponseFactoryInterface; /** @var ResponseFactoryInterface $responseFactory */ /** @var Manager $jsonApiManager */ $middleware = new JsonApiMiddleware($responseFactory, $jsonApiManager); // Add the middleware to any PSR-15 compatible library/framework, such as Slim, Mezzio, etc
Console command
use Symfony\Component\Console\Application; use Jgut\Slim\PHPDI\Command\ListCommand; /** @var \Slim\App $app */ $container = $app->getContainer(); $cli = new Application('Slim CLI'); $cli->add(new ListCommand($container)); $app->run();
List container definitions
List defined container definitions supporting searching
Resource mapping
Resources can be defined in two basic ways: by writing them down in definition files of various types or directly defined in attributes on classes
Attributes
ResourceObject (Class level)
Identifies each JSON:API resource. Its presence is mandatory in each resource class
Accepts an optional "name" that overrides default (class name with lowercase first letter)
use Jgut\JsonApi\Mapping\Attribute\ResourceObject; use Jgut\JsonApi\Mapping\Attribute\ResourcePrefix; use Jgut\JsonApi\Mapping\Attribute\ResourceSchema; #[ResourceObject( name: 'company', prefix: 'resourcePrefix', schema: 'customSchemaClass', meta: ['meta1' => 'value'], )] class Company { }
name
, optional, resource name, lowercase first letter class name by defaultprefix
, optional, resource url prefix when links are includedschema
, optional, class name implementing \Jgut\JsonApi\Schema\MetadataSchemaInterface. Override default one
Identifier (Property level)
The resource identifier
use Jgut\JsonApi\Mapping\Attribute\Getter; use Jgut\JsonApi\Mapping\Attribute\Identifier; use Jgut\JsonApi\Mapping\Attribute\ResourceObject; use Jgut\JsonApi\Mapping\Attribute\Setter; #[ResourceObject] class Owner { #[Identifier( name: 'identifier', getter: 'getIdentifier', setter: 'setIdentifier', meta: ['meta1' => 'value'], )] protected string $id; }
name
, optional, identifier name, lowercase first letter property name by defaultgetter
, optional, method in the class that gives access to the property. By default, uppercase first letter property name prefixed by "is" for booleans or "get" for the rest of typessetter
, optional, method in the class that sets the value for the property, uppercase first letter property name prefixed by "set"meta
, optional, list of optional array/value array of identifier metadata
Attribute (Property level)
A resource attribute
use Jgut\JsonApi\Mapping\Attribute\Attribute; use Jgut\JsonApi\Mapping\Attribute\Getter; use Jgut\JsonApi\Mapping\Attribute\ResourceObject; use Jgut\JsonApi\Mapping\Attribute\Setter; #[ResourceObject] class Company { #[Attribute( name: 'title', getter: 'getTitle', setter: 'setTitle', groups: ['view'], )] protected string $title; }
name
, optional, attribute name, lowercase first letter property name by defaultgetter
, optional, method in the class that gives access to the property. By default, uppercase first letter property name prefixed by "is" for booleans or "get" for the rest of typessetter
, optional, method in the class that sets the value for the property, uppercase first letter property name prefixed by "set"groups
, optional, array of groups to which the attribute belongs
Relationship (Property level)
A resource relationship
use Jgut\JsonApi\Mapping\Attribute\Relationship; use Jgut\JsonApi\Mapping\Attribute\ResourceObject; #[ResourceObject] class Company { #[Relationship( name: 'owner', getter: 'getOwner', setter: 'setOwner', groups: ['view'], )] protected Owner $companyOwner; }
name
, optional, relationship name, lowercase first letter property name by defaultgetter
, optional, method in the class that gives access to the property. By default, uppercase first letter property name prefixed by "is" for booleans or "get" for the rest of typessetter
, optional, method in the class that sets the value for the property, uppercase first letter property name prefixed by "set"groups
, optional, array of groups to which the relationship belongs
Links
use Jgut\JsonApi\Mapping\Attribute\Link; use Jgut\JsonApi\Mapping\Attribute\LinkRelated; use Jgut\JsonApi\Mapping\Attribute\LinkSelf; use Jgut\JsonApi\Mapping\Attribute\ResourceObject; use Jgut\JsonApi\Mapping\Attribute\Relationship; #[ResourceObject] #[LinkSelf(false)] #[LinkRelated] #[Link( href: 'http://...', title: 'example', meta: ['meta1' => 'value'], )] class Company { #[Relationship] #[LinkSelf] #[LinkRelated(false)] #[Link( href: 'http://...', title: 'example', meta: ['meta1' => 'value'], )] protected Owner $companyOwner; }
LinkSelf (Class level)
Determines whether self link is included in the response
LinkRelated (Class level)
Determines whether self link is included in the response when the resource is included as a relationship
Link (Class and Property level)
Adds as many custom link to the resource or field as needed
href
, required, href of the linktitle
, optional, link titlemeta
, optional, list of optional link metadata (see metadata section below)
Metadata
use Jgut\JsonApi\Mapping\Attribute\Attribute; use Jgut\JsonApi\Mapping\Attribute\Meta; use Jgut\JsonApi\Mapping\Attribute\Relationship; use Jgut\JsonApi\Mapping\Attribute\ResourceObject; #[ResourceObject] #[Meta(key: 'meta1', value: 'value')] class Company { #[Identifier] #[Meta(key: 'meta2', value: 'value')] protected string $id; #[Relationship] #[Meta(key: 'meta3', value: 'value')] #[Meta(key: 'meta4', value: 'value')] protected Owner $owner; }
There are two kinds of metadata:
Meta Attribute (Class and Property level)
Assign one or more metadata to a resource, identifier or relationship
key
, required, metadata keyvalue
, required, metadata value
Other metadata
Link attributes accept metadata as a key/value array
Definition files
PHP
return [ [ 'class' => 'CompanyClass', 'name' => 'company', 'prefix' => 'company', 'schema' => 'MetadataCompanySchemaClass', 'linkSelf' => true, 'linkRelated' => false, 'meta' => [ 'meta1' => 'value', ], 'identifier' => [ 'property' => 'uuid', 'name' => 'id', 'getter' => 'getUuid', 'setter' => 'setUuid', 'meta' => [ 'meta2' => 'value', ] ], 'attributes' => [ [ 'property' => 'email', 'name' => 'email', 'getter' => 'getEmail', 'setter' => 'setEmail', ], ], 'relationships' => [ [ 'class' => 'OwnerClass', 'property' => 'owner', 'name' => 'owner', 'linkSelf' => true, 'linkRelated' => true, 'links' => [ 'example' => [ 'href' => 'http://example.com', 'meta' => [ 'meta3' => 'value', ], ], ], 'meta' => [ 'meta4' => 'value', ], ], ], ], ];
JSON
[ { "class": "CompanyClass", "name": "company", "prefix": "company", "schema": "MetadataCompanySchemaClass", "linkSelf": true, "linkRelated": false, "meta": { "meta1": "value" }, "identifier": { "property": "uuid", "name": "id", "getter": "getUuid", "setter": "setUuid", "meta": { "meta2": "value" } }, "attributes": [ { "property": "email", "name": "email", "getter": "getEmail", "setter": "setEmail" } ], "relationships": [ { "class": "OwnerClass", "property": "owner", "name": "owner", "linkSelf": true, "linkRelated": true, "links": { "example": { "href": "http://example.com", "meta": { "meta3": "value" } } }, "meta": { "meta4": "value" } } ] } ]
XML
<?xml version="1.0" encoding="utf-8"?> <root> <resource class="CompanyClass" name="company" prefix="company" schema="MetadataCompanySchemaClass" linkSelf="true" linkRelated="false" > <meta> <meta1>value</meta1> </meta> <identifier property="uuid" name="id" getter="getUuid" setter="setUuid"> <meta> <meta2>value</meta2> </meta> </identifier> <attributes> <attribute1 property="email" name="email" getter="getEmail" setter="setEmail"/> </attributes> <relationships> <relationship1 class="OwnerClass" property="owner" name="owner" linkSelf="true" linkRelated="true"> <links> <example href="http://example.com"> <meta> <meta3>value</meta3> </meta> </example> </links> <meta> <meta4>value</meta4> </meta> </relationship1> </relationships> </resource> </root>
YAML
- class: "CompanyClass" name: "company" prefix: "company" schema: "MetadataCompanySchemaClass" linkSelf: true linkRelated: false meta: meta1: "value" identifier: property": "uuid" name: "id" getter: "getUuid" setter: "setUuid" meta: meta2: "value" attributes: - property: "email" name: "email" getter: "getEmail" setter: "setEmail" relationships: - class: "OwnerClass" property: "owner" name: "owner" linkSelf: true linkRelated: true links: example: href: "http://example.com" meta: meta3: "value" meta: meta4: "value"
Annotations
Annotations are deprecated and will be removed eventually. Use Attribute mapping when possible.
You need to require Doctrine's annotation package
composer require doctrine/annotations
ResourceObject (Class level)
Identifies each resource. Its presence is mandatory on each resource class
use Jgut\JsonApi\Mapping\Annotation as JJM; /** * @JJM\ResourceObject( * name="company", * schema="CustomSchemaClass", * prefix="resourcePrefix", * linkSelf=true, * linkRelated=false, * links={"link1": "http://...", "link2": "http://..."}, * meta={"meta1" => "value", "meta2" => "value"} * ) */ class Company { }
name
, optional, resource name, lowercase first letter class name by defaultprefix
, optional, resource url prefix when links are includedschema
, optional, class name implementing \Jgut\JsonApi\Schema\MetadataSchemaInterface. Override default onelinkSelf
, optional bool, display self link, null by defaultlinkRelated
, optional bool, display self link when included, null by defaultlinks
, optional, list of optional key/value array of resource linksmeta
, optional, list of optional array/value array of resource metadata
Identifier (Property level)
The resource identifier
use Jgut\JsonApi\Mapping\Annotation as JJM; /** * @JJM\ResourceObject */ class Owner { /** * @JJM\Identifier( * name="id", * getter="getId", * setter="setId", * meta={"meta1" => "value", "meta2" => "value"} * ) */ protected $id; }
name
, optional, identifier name, lowercase first letter property name by defaultgetter
, optional, method in the class that gives access to the property. By default, uppercase first letter property name prefixed by "is" for booleans or "get" for the rest of typessetter
, optional, method in the class that sets the value for the property, uppercase first letter property name prefixed by "set"meta
, optional, list of optional array/value array of identifier metadata
Attribute (Property level)
Defines each and every attribute accessible on the resource
use Jgut\JsonApi\Mapping\Annotation as JJM; /** * @JJM\ResourceObject */ class Company { /** * @JJM\Attribute( * name="email", * getter="getEmail", * setter="setEmail", * groups={"view"} * ) */ protected string $email; }
name
, optional, attribute name, lowercase first letter property name by defaultgetter
, optional, method in the class that gives access to the property. By default, uppercase first letter property name prefixed by "is" for booleans or "get" for the rest of typessetter
, optional, method in the class that sets the value for the property, uppercase first letter property name prefixed by "set"groups
, optional, array of groups to which the attribute belongs
Relationship (Property level)
Identifies this resource relationships
use Jgut\JsonApi\Mapping\Annotation as JJM; /** * @JJM\ResourceObject */ class Company { /** * @JJM\Relationship( * name="company", * getter="getCompany", * setter="setCompany", * groups=["view"] * linkSelf=true, * linkRelated=false, * links={"link1": "http://...", "link2": "http://..."], * meta={"meta1" => ·"value", "meta2" => "value"} * ) */ protected Owner $company; }
name
, optional, relationship name, lowercase first letter property name by defaultgetter
, optional, method in the class that gives access to the property. By default, uppercase first letter property name prefixed by "is" for booleans or "get" for the rest of typessetter
, optional, method in the class that sets the value for the property, uppercase first letter property name prefixed by "set"groups
, optional, array of groups to which the relationship belongslinkSelf
, optional bool, display self link, null by defaultlinkRelated
, optional bool, display self link when included, null by defaultlinks
, optional, list of optional key/value array of resource linksmeta
, optional, list of optional array/value array of relationship metadata
Contributing
Found a bug or have a feature request? Please open a new issue. Have a look at existing issues before.
See file CONTRIBUTING.md
License
See file LICENSE included with the source code for a copy of the license terms.