Weave Code
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 Annotation Bundle Laravel Package

tbn/json-annotation-bundle

Symfony bundle that adds a @Json annotation for controllers to automatically return JSON responses. Wraps successful return arrays and exceptions into a consistent payload (success/data/message), with configurable keys, HTTP codes, and optional POST query echo/auth errors.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require tbn/json-annotation-bundle:dev-master
    

    Add to config/bundles.php (Laravel 5.4+):

    return [
        // ...
        tbn\JsonAnnotationBundle\JsonAnnotationBundle::class => ['all' => true],
    ];
    
  2. First Use Case: Annotate a controller method with @Json() and return an array. The bundle automatically wraps the response in a standardized JSON structure:

    use tbn\JsonAnnotationBundle\Configuration\Json;
    
    class UserController extends Controller
    {
        /**
         * @Route("/api/user", methods={"GET"})
         * @Json()
         */
        public function getUser()
        {
            return ['name' => 'John', 'email' => 'john@example.com'];
        }
    }
    

    Output:

    {
        "success": true,
        "data": {
            "name": "John",
            "email": "john@example.com"
        }
    }
    

Where to Look First

  • Configuration: config/packages/tbn_json_annotation.yaml (if auto-generated) or override in config/packages/dev/tbn_json_annotation.yaml.
  • Events: src/EventListener/ for custom pre-hook logic (e.g., token validation).
  • Exceptions: Defaults to HTTP 500 for errors unless customized.

Implementation Patterns

Core Workflow

  1. Annotation-Driven Responses: Use @Json() on methods returning arrays to enforce consistent API responses. Example:

    /**
     * @Json()
     * @return array
     */
    public function createUser(Request $request)
    {
        $validated = $request->validate(['name' => 'required']);
        return User::create($validated);
    }
    
  2. Exception Handling: Let the bundle handle exceptions automatically. Customize error keys via config:

    tbn_json_annotation:
        exception_message_key: "error_details"
        exception_code: 422
    
  3. POST Data Echo: Enable post_query_back to return request data in responses:

    tbn_json_annotation:
        post_query_back: true
        post_query_key: "input"
    

    Output:

    {
        "success": true,
        "data": {...},
        "input": {"name": "John"}
    }
    
  4. Authentication Errors: Disable default 401/403 responses and use JSON:

    tbn_json_annotation:
        enable_authentication_error: true
    

    Output for Unauthenticated:

    {
        "success": false,
        "message": "Unauthenticated."
    }
    

Integration Tips

  • API Controllers: Group @Json() methods in dedicated controllers (e.g., Api/UserController).
  • Middleware: Combine with api middleware for route grouping:
    Route::prefix('api')->middleware('api')->group(function () {
        Route::get('/users', [UserController::class, 'index']);
    });
    
  • Testing: Mock JsonPreHookEvent in unit tests:
    $event = new JsonPreHookEvent($request, $response);
    $this->assertTrue($event->isValid());
    

Gotchas and Tips

Pitfalls

  1. Annotation Parsing:

    • Ensure @Json() is on the method, not the class. The bundle uses Doctrine annotations under the hood.
    • Fix: Use use tbn\JsonAnnotationBundle\Configuration\Json; at the top of the file.
  2. Non-Array Returns:

    • The bundle expects arrays. Returning strings/objects may break JSON structure.
    • Fix: Cast responses:
      return (array) $this->userRepository->find($id);
      
  3. Event Dispatching:

    • JsonPreHookEvent is dispatched before the method executes. Use it for early validation (e.g., token checks).
    • Gotcha: Events won’t trigger if @Json() is missing.
  4. Configuration Overrides:

    • Bundle settings must be in tbn_json_annotation (not json_annotation). Typos here cause silent failures.

Debugging

  • Check Annotations: Use php bin/console debug:container tbn_json_annotation to verify the bundle is loaded.
  • Log Events: Add a temporary listener to debug JsonPreHookEvent:
    public function onJsonPrehook(JsonPreHookEvent $event)
    {
        \Log::debug('Request:', $event->getRequest()->all());
    }
    
  • Response Inspection: For malformed JSON, inspect the raw response with:
    dd($this->get('response')->getContent());
    

Extension Points

  1. Custom Events: Extend JsonPreHookEvent to add metadata:

    class CustomJsonEvent extends JsonPreHookEvent
    {
        public function setCustomData(array $data) { ... }
    }
    

    Dispatch via:

    $this->get('event_dispatcher')->dispatch(
        'json.pre_hook',
        new CustomJsonEvent($request, $response)
    );
    
  2. Response Transformers: Override the response logic by binding a custom service:

    services:
        tbn_json_annotation.response_transformer:
            class: App\Service\CustomJsonTransformer
            tags: ['tbn_json_annotation.transformer']
    
  3. Authentication: Replace default auth errors by implementing JsonAuthenticationListener:

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        if ($event->getThrowable() instanceof AuthenticationException) {
            $event->setResponse(new JsonResponse([
                'success' => false,
                'message' => 'Custom auth message'
            ]));
        }
    }
    

Pro Tips

  • DRY Controllers: Use traits to avoid repeating @Json() and validation logic.
  • API Versioning: Combine with api middleware and version prefixes:
    Route::prefix('api/v1')->group(...);
    
  • Performance: Cache annotation parsing in production by enabling OPcache.
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.
babenkoivan/elastic-client
innmind/static-analysis
innmind/coding-standard
datacore/hub-sdk
alengo/sulu-http-cache-bundle
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme
agtp/agtp-php
agtp/mod-php
centraldesktop/protobuf-php