jaspr/mapper

JSON API implementation, by annotations or schemas.

5.5.2 2024-12-16 12:43 UTC

README

Implementation of JSON API Standard Specification

This project goal is to create easy-to-use library to implement JSON API specification.

Whole project is at the beginning of development. So don't hesitate to help. I'm open to some good ideas how make this more customizable and friendly.

Library only provides wrappers to create valid JSON API document. Controllers and Response is on you.

Issues

You can write email or create issue in gitlab

Installation

Install library via Composer

composer require jaspr/mapper

Basic Usage

For simplicity, we use $container as some dependency provider (Dependency Injection).

Describing your objects

You can choose which way you want to describe your object metadata.

With Annotations

Note: If you want to use annotations you have to use AnnotationDriver in MetadataFactory

Example

How you can see, setting up resource object is quiet easy. Just annotate your getter with `#[Attribute] or #[Relationship]` annotation.

Schema

The important part is to implement Resource interface. Then fill up static method getSchema.

Note: If you want to use schema you have to use SchemaDriver in MetadataFactory

Example

MetadataRepository

To create MetadataRepository we must use MetadataFactory.

Usage

<?php
/** @var $container Psr\Container\ContainerInterface */
// This is cache instance implements PSR SimpleCache
$cache = $container->get( Psr\SimpleCache\CacheInterface::class);
// This is AnnotationDriver or SchemaDriver, depends on your preferences
$driver = $container->get(\JSONAPI\Driver\Driver::class);
// Paths to your object representing resources
$paths = ['paths/to/your/resources','another/path'];
// Factory returns instance of MetadataRepository
$repository = JSONAPI\Factory\MetadataFactory::create(
            $paths,
            $cache,
            $driver
        );

Encoder

Options

ParamDefaultDescription
repositoryInstance of MetadataRepository.

Usage

<?php

// First we need DocumentBuilderFactory
// Let's get MetadataRepository from DI
/** @var $container Psr\Container\ContainerInterface */
$metadataRepository = $container->get(JSONAPI\Metadata\MetadataRepository::class);
$encoder = \JSONAPI\Mapper\Encoding\EncoderFactory::createDefaultEncoder($metadataRepository)
$data = new \JSONAPI\Mapper\Test\Resources\Valid\GettersExample('id');
/** @var \JSONAPI\Mapper\Document\ResourceObjectIdentifier $identifier */
$identifier = $encoder->identify($data);
/** @var \JSONAPI\Mapper\Document\ResourceObject $resource */
$resource = $encoder->encode($data);
/** @var \JSONAPI\Mapper\Document\Document $document */
$document = $encoder->compose($data);


Request Parser

This object works with url, and parse required keywords as described at JSON API Standard

Options

ParamDefaultDescription
baseUrlURL where you API lays. Must end with / to work properly with relative links.
repositoryInstance of MetadataRepository.
pathParserPathParserInstance of PathParserInterface. Provides information about path, like resource type, resource ID, relation type, is it collection or is it relationship.
paginationParserOffsetStrategyParserInstance of PaginationParserInterface. Pagination.
sortParserSortParserInstance of SortParserInterface. Sort.
inclusionParserInclusionParserInstance of InclusionParserInterface. Inclusion.
fieldsetParserFieldsetParserInstance of FieldsetParserInterface. Sparse Fields
filterParserExpressionFilterParserFilterParserInterface instance, which is responsible for parsing filter. Filter
bodyParserBodyParserInstance of BodyParserInterface.
loggerNullLoggerLoggerInterface instance, PSR compliant logger instance.

Filter

As described, specification is agnostic about filter implementation. So I created, more like borrowed, expression filter from OData. So now you can use something like this:

?filter=stringProperty eq 'string' and contains(stringProperty,'asdf') and intProperty in (1,2,3) or boolProperty ne true and relation.property eq null

Or if you have simpler use cases you can try QuatrodotFilter:

?filter=stringProperty::contains::Bonus|boolProperty::eq::true

Pagination

I implement two of three pagination technics

  • LimitOffsetPagination
  • PagePagination

Includes

https://jsonapi.org/format/#fetching-includes

Sort

https://jsonapi.org/format/#fetching-sorting

Index Page

If you want use JASPR SDK to its full potential, consider expose index page.

<?php
$doc      = new JSONAPI\Mapper\IndexDocument(self::$mr, self::$url);
$response = json_encode($doc);

which returns something like this:

{
    "jsonapi": {
        "version": "1.0"
    },
    "links": {
        "relation": "https:\/\/unit.test.org\/relation",
        "getter": "https:\/\/unit.test.org\/getter",
        "meta": "https:\/\/unit.test.org\/meta",
        "prop": "https:\/\/unit.test.org\/prop",
        "third": "https:\/\/unit.test.org\/third"
    },
    "meta": {
        "title": "JSON:API Index Page",
        "baseUrl": "https:\/\/unit.test.org/"
    }
}

And if your front-end use jaspr/client-js library, then you can use useJsonApiWithIndex factory to enjoy RESTful experience.

Open API Schema

This library provides lightweight wrapper around OAS. It can generate OAS v3.0.3 schema in json, so you can provide doc for your api easily.

Basic Example

    $factory = new OpenAPISpecificationBuilder(
        $metadataRepository,
        'https://your.api.url'
    );

    $info = new Info('JSON:API OAS', '1.0.0');
    $info->setDescription('Test specification');
    $info->setContact(
        (new Contact())
            ->setName('Tomas Benedikt')
            ->setEmail('tomas.benedikt@gmail.com')
            ->setUrl('https://gitlab.com/jaspr')
    );
    $info->setLicense(
        (new License('MIT'))
            ->setUrl('https://gitlab.com/jaspr/mapper/-/blob/5.x/LICENSE')
    );
    $info->setTermsOfService('https://gitlab.com/jaspr/mapper/-/blob/5.x/CONTRIBUTING.md');

    $oas = $factory->create($info);
    $oas->setExternalDocs(new ExternalDocumentation('https://gitlab.com/jaspr/mapper/-/wikis/home'));

    $json = json_encode($oas);

For more examples, try look at tests