Skip to content

Instantly share code, notes, and snippets.

@gmorel
Created June 16, 2021 13:17
Show Gist options
  • Save gmorel/46c74940fc53a81860c202f373d7bb4c to your computer and use it in GitHub Desktop.
Save gmorel/46c74940fc53a81860c202f373d7bb4c to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
namespace App\Common\UI\Json;
use App\Common\UI\Normalizer\Json;
use App\Common\UI\Normalizer\Normalizer;
use App\Common\UI\Normalizer\V1\FormErrorRfc7807Normalizer;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
/**
* Handle how a JSON payload should be presented.
*
* @author Guillaume MOREL <me@gmorel.io>
*/
class JsonPayloadHandler
{
private Normalizer $restNormalizer;
public function __construct(Normalizer $restNormalizer)
{
$this->restNormalizer = $restNormalizer;
}
/**
* @param mixed $content
*/
public function createJsonResponse($content, int $httpCode = Response::HTTP_OK, array $headers = []): JsonResponse
{
return new JsonResponse($content, $httpCode, $headers);
}
/**
* Not returning 204 No Content as not really supported by Angular2..
*
* @param bool $real If true, send a real 204, not a 200
*/
public function createEmptyJsonResponse(bool $real = false): JsonResponse
{
$statusCode = Response::HTTP_OK;
if (true === $real) {
$statusCode = Response::HTTP_NO_CONTENT;
}
return new JsonResponse(null, $statusCode);
}
/**
* @param mixed $content
*/
public function createJsonResponseNormalized(
$content,
int $httpCode = Response::HTTP_OK,
array $headers = [],
array $normalizerOptions = [],
string $rootNodeName = null
): JsonResponse {
$normalizedContent = $this->restNormalizer->normalize($content, $normalizerOptions);
if ($normalizedContent instanceof \JsonSerializable) {
// Manually trigger the JsonSerializable::jsonSerialize() chain for PHP 5.3.
$data = $normalizedContent->jsonSerialize();
$data = $this->appendRootNodeName($data, $rootNodeName);
return $this->createJsonResponse($data, $httpCode, $headers);
}
if (\is_array($normalizedContent)) {
// Trick to allow us to encapsulate a normalized data in an array in controller: array("items" => ...).
$data = Json::arrayNode($normalizedContent);
$data = $this->appendRootNodeName($data, $rootNodeName);
return $this->createJsonResponse($data, $httpCode, $headers);
}
throw new \LogicException(sprintf('The result of the normalizer is not serializable in JSON. A "\JsonSerializable" object or an array is expected. Actual: "%s".', get_class($normalizedContent)));
}
public function createJsonErrorResponseNormalized(string $propertyPath, string $message, int $status = JsonResponse::HTTP_BAD_REQUEST): JsonResponse
{
return new JsonResponse(
FormErrorRfc7807Normalizer::createDto(
$propertyPath,
$message
),
$status
);
}
/**
* @param mixed $data
*/
private function appendRootNodeName($data, string $rootNodeName = null)
{
if (null !== $rootNodeName) {
return [$rootNodeName => $data];
}
return $data;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment