Skip to content

Commit 84b225d

Browse files
[JsonPath] Add FrameworkBundle integration
1 parent 29da4f5 commit 84b225d

File tree

9 files changed

+208
-77
lines changed

9 files changed

+208
-77
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use Symfony\Component\HttpClient\HttpClient;
3232
use Symfony\Component\HttpFoundation\Cookie;
3333
use Symfony\Component\HttpFoundation\IpUtils;
34+
use Symfony\Component\JsonPath\JsonPath;
3435
use Symfony\Component\JsonStreamer\StreamWriterInterface;
3536
use Symfony\Component\Lock\Lock;
3637
use Symfony\Component\Lock\Store\SemaphoreStore;
@@ -184,6 +185,7 @@ public function getConfigTreeBuilder(): TreeBuilder
184185
$this->addWebhookSection($rootNode, $enableIfStandalone);
185186
$this->addRemoteEventSection($rootNode, $enableIfStandalone);
186187
$this->addJsonStreamerSection($rootNode, $enableIfStandalone);
188+
$this->addJsonPathSection($rootNode, $enableIfStandalone);
187189

188190
return $treeBuilder;
189191
}
@@ -2742,4 +2744,16 @@ private function addJsonStreamerSection(ArrayNodeDefinition $rootNode, callable
27422744
->end()
27432745
;
27442746
}
2747+
2748+
private function addJsonPathSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
2749+
{
2750+
$rootNode
2751+
->children()
2752+
->arrayNode('json_path')
2753+
->info('JsonPath configuration')
2754+
->{$enableIfStandalone('symfony/json-path', JsonPath::class)}()
2755+
->end()
2756+
->end()
2757+
;
2758+
}
27452759
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
107107
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
108108
use Symfony\Component\HttpKernel\Log\DebugLoggerConfigurator;
109+
use Symfony\Component\JsonPath\JsonPath;
109110
use Symfony\Component\JsonStreamer\Attribute\JsonStreamable;
110111
use Symfony\Component\JsonStreamer\JsonStreamWriter;
111112
use Symfony\Component\JsonStreamer\StreamReaderInterface;
@@ -474,6 +475,10 @@ public function load(array $configs, ContainerBuilder $container): void
474475
$this->registerJsonStreamerConfiguration($config['json_streamer'], $container, $loader);
475476
}
476477

478+
if ($this->readConfigEnabled('json_path', $container, $config['json_path'])) {
479+
$this->registerJsonPathConfiguration($config['json_streamer'], $container, $loader);
480+
}
481+
477482
if ($this->readConfigEnabled('lock', $container, $config['lock'])) {
478483
$this->registerLockConfiguration($config['lock'], $container, $loader);
479484
}
@@ -2119,6 +2124,15 @@ private function registerJsonStreamerConfiguration(array $config, ContainerBuild
21192124
}
21202125
}
21212126

2127+
private function registerJsonPathConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
2128+
{
2129+
if (class_exists(JsonPath::class)) {
2130+
throw new LogicException('JsonPath support cannot be enabled as the JsonPath component is not installed. Try running "composer require symfony/json-path".');
2131+
}
2132+
2133+
$loader->load('json_path.php');
2134+
}
2135+
21222136
private function registerPropertyInfoConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
21232137
{
21242138
if (!interface_exists(PropertyInfoExtractorInterface::class)) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
13+
14+
use Symfony\Component\JsonPath\JsonCrawler;
15+
use Symfony\Component\JsonPath\JsonCrawlerInterface;
16+
17+
return static function (ContainerConfigurator $container) {
18+
$container->services()
19+
->set('json_path.crawler', JsonCrawler::class)
20+
->alias(JsonCrawlerInterface::class, 'json_path.crawler');
21+
};

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Symfony\Component\DependencyInjection\ContainerBuilder;
2323
use Symfony\Component\HtmlSanitizer\HtmlSanitizer;
2424
use Symfony\Component\HttpClient\HttpClient;
25+
use Symfony\Component\JsonPath\JsonPath;
2526
use Symfony\Component\JsonStreamer\JsonStreamWriter;
2627
use Symfony\Component\Lock\Store\SemaphoreStore;
2728
use Symfony\Component\Mailer\Mailer;
@@ -1014,6 +1015,9 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor
10141015
'json_streamer' => [
10151016
'enabled' => !class_exists(FullStack::class) && class_exists(JsonStreamWriter::class),
10161017
],
1018+
'json_path' => [
1019+
'enabled' => !class_exists(FullStack::class) && class_exists(JsonPath::class),
1020+
]
10171021
];
10181022
}
10191023

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
"symfony/expression-language": "^6.4|^7.0",
5050
"symfony/html-sanitizer": "^6.4|^7.0",
5151
"symfony/http-client": "^6.4|^7.0",
52+
"symfony/json-path": "7.3.*",
53+
"symfony/json-streamer": "7.3.*",
5254
"symfony/lock": "^6.4|^7.0",
5355
"symfony/mailer": "^6.4|^7.0",
5456
"symfony/messenger": "^6.4|^7.0",
@@ -70,7 +72,6 @@
7072
"symfony/workflow": "^6.4|^7.0",
7173
"symfony/yaml": "^6.4|^7.0",
7274
"symfony/property-info": "^6.4|^7.0",
73-
"symfony/json-streamer": "7.3.*",
7475
"symfony/uid": "^6.4|^7.0",
7576
"symfony/web-link": "^6.4|^7.0",
7677
"symfony/webhook": "^7.2",
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\JsonPath;
13+
14+
use Symfony\Component\JsonPath\Exception\InvalidArgumentException;
15+
use Symfony\Component\JsonPath\Exception\JsonCrawlerException;
16+
17+
/**
18+
* @author Alexandre Daubois <alex.daubois@gmail.com>
19+
*
20+
* @experimental
21+
*/
22+
interface CrawlerInterface
23+
{
24+
/**
25+
* @return list<array|string|float|int|bool|null>
26+
*
27+
* @throws InvalidArgumentException When the data source provided to the crawler cannot be decoded
28+
* @throws JsonCrawlerException When a syntax error occurs in the provided JSON path
29+
*/
30+
public function find(string|JsonPath $query): array;
31+
}

src/Symfony/Component/JsonPath/JsonCrawler.php

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
*
2929
* @experimental
3030
*/
31-
final class JsonCrawler implements JsonCrawlerInterface
31+
final class JsonCrawler implements CrawlerInterface, JsonCrawlerInterface
3232
{
3333
private const RFC9535_FUNCTIONS = [
3434
'length' => true,
@@ -39,16 +39,20 @@ final class JsonCrawler implements JsonCrawlerInterface
3939
];
4040

4141
/**
42-
* @param resource|string $raw
42+
* @param resource|string|array $data
4343
*/
44-
public function __construct(
45-
private readonly mixed $raw,
46-
) {
47-
if (!\is_string($raw) && !\is_resource($raw)) {
48-
throw new InvalidArgumentException(\sprintf('Expected string or resource, got "%s".', get_debug_type($raw)));
44+
public function __construct(private mixed $data = [])
45+
{
46+
if (!\is_string($data) && !\is_resource($data) && !\is_array($data)) {
47+
throw new \TypeError(\sprintf('Argument #1 ($data) must be of type string, array or resource, %s given.', get_debug_type($data)));
4948
}
5049
}
5150

51+
public function fromJson(mixed $data): CrawlerInterface
52+
{
53+
return new self($data);
54+
}
55+
5256
public function find(string|JsonPath $query): array
5357
{
5458
return $this->evaluate(\is_string($query) ? new JsonPath($query) : $query);
@@ -58,29 +62,33 @@ private function evaluate(JsonPath $query): array
5862
{
5963
try {
6064
$tokens = JsonPathTokenizer::tokenize($query);
61-
$json = $this->raw;
65+
$json = $this->data;
6266

63-
if (\is_resource($this->raw)) {
67+
if (\is_resource($this->data)) {
6468
if (!class_exists(Splitter::class)) {
6569
throw new \LogicException('The JsonStreamer package is required to evaluate a path against a resource. Try running "composer require symfony/json-streamer".');
6670
}
6771

6872
$simplified = JsonPathUtils::findSmallestDeserializableStringAndPath(
6973
$tokens,
70-
$this->raw,
74+
$this->data,
7175
);
7276

7377
$tokens = $simplified['tokens'];
7478
$json = $simplified['json'];
7579
}
7680

77-
try {
78-
$data = json_decode($json, true, 512, \JSON_THROW_ON_ERROR);
79-
} catch (\JsonException $e) {
80-
throw new InvalidJsonStringInputException($e->getMessage(), $e);
81-
}
81+
if (\is_array($json)) {
82+
$current = [$json];
83+
} else {
84+
try {
85+
$data = json_decode($json, true, 512, \JSON_THROW_ON_ERROR);
86+
} catch (\JsonException $e) {
87+
throw new InvalidJsonStringInputException($e->getMessage(), $e);
88+
}
8289

83-
$current = [$data];
90+
$current = [$data];
91+
}
8492

8593
foreach ($tokens as $token) {
8694
$next = [];

src/Symfony/Component/JsonPath/JsonCrawlerInterface.php

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@
1111

1212
namespace Symfony\Component\JsonPath;
1313

14-
use Symfony\Component\JsonPath\Exception\InvalidArgumentException;
15-
use Symfony\Component\JsonPath\Exception\JsonCrawlerException;
16-
1714
/**
1815
* @author Alexandre Daubois <alex.daubois@gmail.com>
1916
*
@@ -22,10 +19,7 @@
2219
interface JsonCrawlerInterface
2320
{
2421
/**
25-
* @return list<array|string|float|int|bool|null>
26-
*
27-
* @throws InvalidArgumentException When the JSON string provided to the crawler cannot be decoded
28-
* @throws JsonCrawlerException When a syntax error occurs in the provided JSON path
22+
* @param resource|string|array $data
2923
*/
30-
public function find(string|JsonPath $query): array;
24+
public function fromJson(mixed $data): CrawlerInterface;
3125
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy