Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Json Api Specifications Laravel Package

ekanto/json-api-specifications

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require ekanto/json-api-specifications
    

    Register the bundle in config/app.php (if using Symfony) or publish the config:

    php artisan vendor:publish --provider="Ekanto\JASpecificationBundle\JASpecificationBundle"
    
  2. First Use Case: Basic Resource Transformation Define a resource class (e.g., PostResource):

    namespace App\Resources;
    
    use Ekanto\JASpecificationBundle\Resource\ResourceInterface;
    use Ekanto\JASpecificationBundle\Resource\ResourceTrait;
    use App\Models\Post;
    
    class PostResource implements ResourceInterface
    {
        use ResourceTrait;
    
        protected $model;
    
        public function __construct(Post $post)
        {
            $this->model = $post;
        }
    
        public function getType()
        {
            return 'posts';
        }
    
        public function getId()
        {
            return $this->model->id;
        }
    
        public function getAttributes()
        {
            return [
                'title' => $this->model->title,
                'body' => $this->model->body,
            ];
        }
    }
    
  3. Serialize a Resource Use the ResourceSerializer to convert a resource to JSON:API format:

    use Ekanto\JASpecificationBundle\Serializer\ResourceSerializer;
    
    $serializer = new ResourceSerializer();
    $postResource = new PostResource($post);
    $jsonApiData = $serializer->serialize($postResource);
    

Implementation Patterns

Common Workflows

  1. Resource Nesting (Relationships) Define relationships in your resource:

    public function getRelationships()
    {
        return [
            'author' => new AuthorResource($this->model->author),
        ];
    }
    
  2. Pagination Use the Pagination class to handle pagination metadata:

    use Ekanto\JASpecificationBundle\Serializer\Pagination;
    
    $pagination = new Pagination($posts->total(), $posts->perPage(), $posts->currentPage());
    $serializer->setPagination($pagination);
    
  3. Customizing Serialization Override default behavior by extending the ResourceSerializer:

    class CustomSerializer extends ResourceSerializer
    {
        protected function getAttribute($resource, $key)
        {
            // Custom logic for specific attributes
            if ($key === 'title') {
                return strtoupper($resource->getAttributes()['title']);
            }
            return parent::getAttribute($key);
        }
    }
    
  4. API Controller Integration Example controller method:

    public function index()
    {
        $posts = Post::paginate(10);
        $resources = $posts->map(fn ($post) => new PostResource($post));
        $serializer = new ResourceSerializer();
        $serializer->setPagination(new Pagination(...));
        return response()->json($serializer->serializeCollection($resources));
    }
    
  5. Deserialization (Parsing JSON:API Requests) Use ResourceDeserializer to parse incoming JSON:API requests:

    use Ekanto\JASpecificationBundle\Serializer\ResourceDeserializer;
    
    $deserializer = new ResourceDeserializer();
    $data = $deserializer->deserialize($request->getContent(), PostResource::class);
    

Integration Tips

  • Laravel HTTP Requests Parse JSON:API requests directly from Laravel's Request object:

    $data = $deserializer->deserialize($request->getContent());
    
  • Form Request Validation Validate incoming JSON:API data using Laravel's FormRequest:

    public function rules()
    {
        return [
            'data.attributes.title' => 'required|string',
            'data.attributes.body' => 'required|string',
        ];
    }
    
  • API Versioning Combine with Laravel's API versioning middleware to support multiple JSON:API versions.

  • Testing Use ResourceSerializer and ResourceDeserializer in PHPUnit tests to validate API responses/requests:

    $serializer = new ResourceSerializer();
    $json = $serializer->serialize($resource);
    $this->assertJsonStringEqualsJson($expectedJson, $json);
    

Gotchas and Tips

Pitfalls

  1. Attribute Whitelisting The serializer only includes attributes explicitly defined in getAttributes(). Omitting an attribute will not include it in the output, even if the model has it. Use getAdditionalAttributes() to include dynamic or all attributes:

    public function getAdditionalAttributes()
    {
        return ['created_at', 'updated_at'];
    }
    
  2. Relationship Data Structure Relationships must return a ResourceInterface or an array of ResourceInterface. Returning raw data (e.g., ['id' => 1]) will cause errors.

  3. ID Field Naming The serializer expects the ID field to be named id. If your model uses a different field (e.g., uuid), override getId():

    public function getId()
    {
        return $this->model->uuid;
    }
    
  4. Pagination Metadata Ensure pagination metadata is set before serializing collections. Missing pagination will result in invalid JSON:API output.

  5. Deserialization Edge Cases

    • Nested relationships in deserialization require careful handling. Use setDataLoader on ResourceDeserializer to resolve nested resources:
      $deserializer->setDataLoader(function ($type, $id) {
          return Post::findOrFail($id);
      });
      
    • Partial updates (PATCH) may require custom logic to merge existing and incoming data.

Debugging Tips

  1. Enable Debug Mode Set the debug config option to true to get detailed error messages:

    'debug' => env('APP_DEBUG', false),
    
  2. Validate JSON:API Output Use tools like JSON:API Validator to validate your API responses.

  3. Log Serialized Data Log the output of ResourceSerializer to debug issues:

    \Log::debug('Serialized JSON:API', ['data' => $serializer->serialize($resource)]);
    
  4. Check for Deprecated Methods Monitor deprecation warnings in the package updates. Some methods may change between minor versions.


Extension Points

  1. Custom Attribute Transformers Extend ResourceSerializer to transform attributes dynamically:

    protected function transformAttribute($resource, $key, $value)
    {
        if ($key === 'body') {
            return Str::limit($value, 200);
        }
        return $value;
    }
    
  2. Custom Error Handling Override error handling in ResourceDeserializer to customize validation errors:

    protected function handleError($error)
    {
        throw new \InvalidArgumentException("Custom error: {$error->getMessage()}");
    }
    
  3. Adding Custom Metadata Extend the serializer to include custom metadata in the top-level object:

    public function getMeta()
    {
        return [
            'custom_field' => 'value',
        ];
    }
    
  4. Support for Polymorphic Relationships Implement logic to handle polymorphic relationships (e.g., author could be a User or Guest):

    public function getRelationships()
    {
        $author = $this->model->author;
        $resource = $author instanceof User
            ? new UserResource($author)
            : new GuestResource($author);
        return ['author' => $resource];
    }
    
  5. Caching Serialized Responses Cache serialized resources to improve performance:

    $cacheKey = "posts.{$post->id}";
    $json = Cache::remember($cacheKey, now()->addHours(1), function () use ($serializer, $postResource) {
        return $serializer->serialize($postResource);
    });
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus