Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/Illuminate/Collections/Arr.php
Original file line number Diff line number Diff line change
Expand Up @@ -1223,4 +1223,28 @@ public static function wrap($value)

return is_array($value) ? $value : [$value];
}

/**
* Tries to parse the given JSON into an array.
*
* @param string $json
* @param bool|null $associative
* @param int $depth
* @param int-mask-of<JSON_BIGINT_AS_STRING|JSON_INVALID_UTF8_IGNORE|JSON_INVALID_UTF8_SUBSTITUTE|JSON_OBJECT_AS_ARRAY|JSON_THROW_ON_ERROR> $flags
*/
public static function fromJson(string $json, ?bool $associative = true, int $depth = 512, int $flags = 0): array
{
if (! json_validate($json, $depth, JSON_INVALID_UTF8_IGNORE & $flags == JSON_INVALID_UTF8_IGNORE ? JSON_INVALID_UTF8_IGNORE : 0)) {
$errorMessage = json_last_error_msg();
throw new InvalidArgumentException('Please provide a valid JSON: '.$errorMessage);
}

$array = json_decode($json, $associative, $depth, $flags);

if (! is_array($array)) {
throw new InvalidArgumentException('The given JSON cannot be parsed into an array: '.get_debug_type($array).' given instead.');
}

return $array;
}
}
41 changes: 41 additions & 0 deletions tests/Support/SupportArrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Illuminate\Support\ItemNotFoundException;
use Illuminate\Support\MultipleItemsFoundException;
use InvalidArgumentException;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use stdClass;
use WeakMap;
Expand Down Expand Up @@ -1812,4 +1813,44 @@ public function testPartition()

$this->assertEquals([[0 => 'John', 1 => 'Jane'], [2 => 'Greg']], $result);
}

public static function provideFromJsonInvalid()
{
return [
'invalid JSON: JSON_ERROR_SYNTAX' => ['}', false, 512, 0, 'Please provide a valid JSON: Syntax error'],
'invalid JSON: JSON_ERROR_UTF8' => ["[\"\u{D800}\"]", false, 512, 0, 'Please provide a valid JSON: Malformed UTF-8 characters, possibly incorrectly encoded'],
'invalid JSON: JSON_ERROR_DEPTH' => ['[[[[]]]]', false, 2, 0, 'Please provide a valid JSON: Maximum stack depth exceeded'],
'non-array JSON: null' => ['null', false, 512, 0, 'The given JSON cannot be parsed into an array: null given instead'],
'non-array JSON: integer' => ['42', false, 512, 0, 'The given JSON cannot be parsed into an array: int given instead'],
'non-array JSON: double/float' => ['42.1', false, 512, 0, 'The given JSON cannot be parsed into an array: float given instead'],
'non-array JSON: string' => ['"foo"', false, 512, 0, 'The given JSON cannot be parsed into an array: string given instead'],
'non-array JSON: boolean' => ['true', false, 512, 0, 'The given JSON cannot be parsed into an array: bool given instead'],
'non-array JSON: object with assoc arg' => ['{"foo": "bar"}', false, 512, 0, 'The given JSON cannot be parsed into an array: stdClass given instead'],
];
}

#[DataProvider('provideFromJsonInvalid')]
public function testFromJsonFails(string $json, ?bool $associative, int $depth, int $flags, string $exceptionMessage)
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage($exceptionMessage);
Arr::fromJson($json, $associative, $depth, $flags);
}

public static function provideFromJsonValid()
{
return [
'list strict' => ['[1, 2, 3]', false, 512, 0, [1, 2, 3]],
'list loose with array flag' => ['[1, 2, 3]', null, 512, JSON_OBJECT_AS_ARRAY, [1, 2, 3]],
'list loose with assoc arg' => ['[1, 2, 3]', true, 512, 0, [1, 2, 3]],
'hashmap loose with array flag' => ['{"foo": "bar"}', null, 512, JSON_OBJECT_AS_ARRAY, ['foo' => 'bar']],
'hashmap loose with assoc arg' => ['{"foo": "bar"}', true, 512, 0, ['foo' => 'bar']],
];
}

#[DataProvider('provideFromJsonValid')]
public function testFromJsonSuccessful(string $json, ?bool $associative, int $depth, int $flags, array $expected)
{
$this->assertEquals($expected, Arr::fromJson($json, $associative, $depth, $flags));
}
}