diff --git a/README.md b/README.md index 1fa1d30c..804c8442 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ $ composer require localheinz/json-normalizer This package comes with the following normalizers: * [`Localheinz\Json\Normalizer\CallableNormalizer`](#callablenormalizer) +* [`Localheinz\Json\Normalizer\ChainNormalizer`](#chainnormalizer) * [`Localheinz\Json\Normalizer\FinalNewLineNormalizer`](#finalnewlinenormalizer) * [`Localheinz\Json\Normalizer\IndentNormalizer`](#indentnormalizer) * [`Localheinz\Json\Normalizer\JsonEncodeNormalizer`](#jsonencodenormalizer) @@ -62,6 +63,33 @@ $normalized = $normalizer->normalize($json); The normalized version will now have the callable applied to it. +### `ChainNormalizer` + +If you want to apply multiple normalizers in a chain, you can use the `ChainNormalizer`. + +```php +use Localheinz\Json\Normalizer; + +$json = <<<'JSON' +{ + "name": "Andreas Möller", + "url": "https://localheinz.com" +} +JSON; + +$normalizer = new Normalizer\ChainNormalizer( + new Normalizer\JsonEncodeNormalizer(JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), + new Normalizer\IndentNormalizer(' '), + new Normalizer\FinalNewLineNormalizer() +); + +$normalized = $normalizer->normalize($json); +``` + +The normalized version will now contain the result of applying all normalizers in a chain, one after another. + +:bulb: Be careful with the order of the normalizers, as one normalizer might override changes a previous normalizer applied. + ### `FinalNewLineNormalizer` If you want to ensure that a JSON file has a single final new line, you can use the `FinalNewLineNormalizer`. diff --git a/src/ChainNormalizer.php b/src/ChainNormalizer.php new file mode 100644 index 00000000..21a6c90e --- /dev/null +++ b/src/ChainNormalizer.php @@ -0,0 +1,43 @@ +normalizers = $normalizers; + } + + public function normalize(string $json): string + { + if (null === \json_decode($json) && JSON_ERROR_NONE !== \json_last_error()) { + throw new \InvalidArgumentException(\sprintf( + '"%s" is not valid JSON.', + $json + )); + } + + foreach ($this->normalizers as $normalizer) { + $json = $normalizer->normalize($json); + } + + return $json; + } +} diff --git a/test/Unit/ChainNormalizerTest.php b/test/Unit/ChainNormalizerTest.php new file mode 100644 index 00000000..39448d2e --- /dev/null +++ b/test/Unit/ChainNormalizerTest.php @@ -0,0 +1,75 @@ +faker()->numberBetween(3, 5); + + $json = <<<'JSON' +{ + "name": "Andreas Möller", + "url": "https://localheinz.com", + "normalized-by": "%s" +} +JSON; + + $normalize = function (string $json, int $index) { + return \sprintf( + $json, + $index + ); + }; + + $normalized = $normalize( + $json, + $count - 1 + ); + + $normalizers = \array_fill(0, $count, null); + + $normalizers = \array_map(function (int $index) use ($json, $normalize) { + $normalized = $normalize( + $json, + $index + ); + + if (0 < $index) { + $json = $normalize( + $json, + $index - 1 + ); + } + + $normalizer = $this->prophesize(NormalizerInterface::class); + + $normalizer + ->normalize(Argument::exact($json)) + ->shouldBeCalled() + ->willReturn($normalized); + + return $normalizer->reveal(); + }, \array_keys($normalizers)); + + $normalizer = new ChainNormalizer(...$normalizers); + + $this->assertSame($normalized, $normalizer->normalize($json)); + } +}