[HttpFoundation] Add Request::toArray() for JSON content

This commit is contained in:
Nyholm 2020-09-17 16:41:40 +02:00 committed by Fabien Potencier
parent 127724d519
commit 83c1a2666d
4 changed files with 76 additions and 0 deletions

View File

@ -8,6 +8,7 @@ CHANGELOG
* added `HeaderUtils::parseQuery()`: it does the same as `parse_str()` but preserves dots in variable names
* added `File::getContent()`
* added ability to use comma separated ip addresses for `RequestMatcher::matchIps()`
* added `Request::toArray()` to parse a JSON request body to an array
* added `RateLimiter\RequestRateLimiterInterface` and `RateLimiter\AbstractRequestRateLimiter`
5.1.0

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpFoundation\Exception;
/**
* Thrown by Request::toArray() when the content cannot be JSON-decoded.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
final class JsonException extends \UnexpectedValueException implements RequestExceptionInterface
{
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\HttpFoundation;
use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException;
use Symfony\Component\HttpFoundation\Exception\JsonException;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
@ -1569,6 +1570,34 @@ class Request
return $this->content;
}
/**
* Gets the request body decoded as array, typically from a JSON payload.
*
* @throws JsonException When the body cannot be decoded to an array
*/
public function toArray(): array
{
if ('' === $content = $this->getContent()) {
throw new JsonException('Response body is empty.');
}
try {
$content = json_decode($content, true, 512, \JSON_BIGINT_AS_STRING | (\PHP_VERSION_ID >= 70300 ? \JSON_THROW_ON_ERROR : 0));
} catch (\JsonException $e) {
throw new JsonException('Could not decode request body.', $e->getCode(), $e);
}
if (\PHP_VERSION_ID < 70300 && \JSON_ERROR_NONE !== json_last_error()) {
throw new JsonException('Could not decode request body: '.json_last_error_msg(), json_last_error());
}
if (!\is_array($content)) {
throw new JsonException(sprintf('JSON content was expected to decode to an array, "%s" returned.', get_debug_type($content)));
}
return $content;
}
/**
* Gets the Etags.
*

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\HttpFoundation\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Exception\JsonException;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpFoundation\InputBag;
use Symfony\Component\HttpFoundation\ParameterBag;
@ -1250,6 +1251,30 @@ class RequestTest extends TestCase
];
}
public function testToArrayEmpty()
{
$req = new Request();
$this->expectException(JsonException::class);
$this->expectExceptionMessage('Response body is empty.');
$req->toArray();
}
public function testToArrayNonJson()
{
$req = new Request([], [], [], [], [], [], 'foobar');
$this->expectException(JsonException::class);
$this->expectExceptionMessageMatches('|Could not decode request body.+|');
$req->toArray();
}
public function testToArray()
{
$req = new Request([], [], [], [], [], [], json_encode([]));
$this->assertEquals([], $req->toArray());
$req = new Request([], [], [], [], [], [], json_encode(['foo' => 'bar']));
$this->assertEquals(['foo' => 'bar'], $req->toArray());
}
/**
* @dataProvider provideOverloadedMethods
*/