1

I try handle all excpetions (Symfony 5) via official documentation: https://symfony.com/doc/current/controller/error_pages.html#overriding-error-output-for-non-html-formats

I want serialize all exception to JSON format. I read solution for similar problem in this topic: How to format all HttpExceptions as json in symfony5? but doesn't resolve my problem.

There my files: src/Controller/ShowController.php

<?php

namespace App\Controller;

use App\Component\ShowResponseHandlerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;

class ShowController extends AbstractController
{
    /**
     * @Route("/show/{file}", name="show", requirements={"file"=".+"})
     */
    public function index(string $file, string $storageDirectory): Response
    {
        $absolutePath = $storageDirectory.$file;
        if(!file_exists($absolutePath)) {
            throw new NotFoundHttpException("Resource not exists");
        }

        return new BinaryFileResponse($absolutePath);

    }
}

src/Serializer/ProblemNormalizer.php

<?php
namespace App\Serializer;

use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class ProblemNormalizer implements NormalizerInterface
{

    public function normalize($exception, string $format = null, array $context = [])
    {
        return [
            'success' => false,
            'exception'=> [
                'message' => $exception->getMessage(),
                'code' => $exception->getStatusCode(),
            ]
        ];
    }

    public function supportsNormalization($data, string $format = null)
    {
        return $data instanceof FlattenException;
    }
}

config/services.yaml

services:
_defaults:
    autowire: true      # Automatically injects dependencies in your services.
    autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

    App\Serializer\ProblemNormalizer:
        tags: ['serializer.normalizer']

and of course i have installed package symfony/serializer

composer show -i | grep "symfony/serializer"

symfony/serializer                 v5.2.9  Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON

What I'm doing wrong or what is not configured? It always return html output.

Update

Console output for:

symfony console debug:container | grep normalizer
  Symfony\Component\Serializer\Normalizer\DenormalizerInterface                alias for "serializer"                                                                     
  Symfony\Component\Serializer\Normalizer\ObjectNormalizer                     alias for "serializer.normalizer.object"                                                   
  Symfony\Component\Serializer\Normalizer\PropertyNormalizer                   alias for "serializer.normalizer.property"                                                 
  maker.auto_command.make_serializer_normalizer                                Symfony\Bundle\MakerBundle\Command\MakerCommand                                            
  maker.maker.make_serializer_normalizer                                       Symfony\Bundle\MakerBundle\Maker\MakeSerializerNormalizer                                  
  serializer.denormalizer.array                                                Symfony\Component\Serializer\Normalizer\ArrayDenormalizer                                  
  serializer.denormalizer.unwrapping                                           Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer                             
  serializer.normalizer.constraint_violation_list                              Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer                  
  serializer.normalizer.data_uri                                               Symfony\Component\Serializer\Normalizer\DataUriNormalizer                                  
  serializer.normalizer.dateinterval                                           Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer                             
  serializer.normalizer.datetime                                               Symfony\Component\Serializer\Normalizer\DateTimeNormalizer                                 
  serializer.normalizer.datetimezone                                           Symfony\Component\Serializer\Normalizer\DateTimeZoneNormalizer                             
  serializer.normalizer.flatten_exception                                      Symfony\Component\Messenger\Transport\Serialization\Normalizer\FlattenExceptionNormalizer  
  serializer.normalizer.form_error                                             Symfony\Component\Serializer\Normalizer\FormErrorNormalizer                                
  serializer.normalizer.json_serializable                                      Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer                         
  serializer.normalizer.mime_message                                           Symfony\Component\Serializer\Normalizer\MimeMessageNormalizer                              
  serializer.normalizer.object                                                 Symfony\Component\Serializer\Normalizer\ObjectNormalizer                                   
  serializer.normalizer.problem                                                Symfony\Component\Serializer\Normalizer\ProblemNormalizer                                  
  serializer.normalizer.property                                               Symfony\Component\Serializer\Normalizer\PropertyNormalizer                                 
  serializer.normalizer.uid                                                    Symfony\Component\Serializer\Normalizer\UidNormalizer                                      

 // To search for a specific service, re-run this command with a search term. (e.g. debug:container log) 
2
  • Could you check that your normalizer is configured running symfony console debug:container | grep normalizer Commented May 24, 2021 at 7:06
  • @qdequippe Yes. I added output from console in my question. Commented May 26, 2021 at 5:14

1 Answer 1

2

Try to remove App\Serializer\ProblemNormalizer from config/services.yaml. Recheck container for normalizers again symfony console debug:container | grep normalizer. Normally you should see your normalizer in the list without any config (Symfony recognizes it by NormalizerInterface). Test with curl http://localhost:8000/show/foo.doc -H "Accept: application/json"

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks!. Reason was. 1. Not needed service: App\Serializer\ProblemNormalizer 2. Second was. I did not send header with accepting response as json: Accept: application/json. Now I have nice response in json format {"success":false,"exception":{"message":"Resource not exists","code":404}}
Consider to use $context: e.g. limit response messages, if($context['debug']) {$message = $exception->getMessage()} else{ $message = $exception->getStatusText()}, you may also add extra data from original exception or translate your message accordingly based on $context['exception'].

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.