Skip to content

Commit

Permalink
Enhancement: Implement JsonEncodeNormalizer
Browse files Browse the repository at this point in the history
  • Loading branch information
localheinz committed Jan 12, 2018
1 parent 8749041 commit ddfc7cc
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ This package comes with the following normalizers:

* [`Localheinz\Json\Normalizer\FinalNewLineNormalizer`](#finalnewlinenormalizer)
* [`Localheinz\Json\Normalizer\IndentNormalizer`](#indentnormalizer)
* [`Localheinz\Json\Normalizer\JsonEncodeNormalizer`](#jsonencodenormalizer)
* [`Localheinz\Json\Normalizer\NoFinalNewLineNormalizer`](#nofinalnewlinenormalizer)

:bulb: All of these normalizers implement the `Localheinz\Json\Normalizer\NormalizerInterface`.
Expand Down Expand Up @@ -71,6 +72,32 @@ $normalized = $normalizer->normalize($json);

The normalized version will now be indented with 2 spaces.

### `JsonEncodeNormalizer`

If you need to adjust the encoding of a JSON file, you can use the `JsonEncodeNormalizer`.

```php
use Localheinz\Json\Normalizer;

$json = <<<'JSON'
{
"name": "Andreas Möller",
"url": "https://localheinz.com"
}
JSON;

$jsonEncodeOptions = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;

$normalizer = new Normalizer\JsonEncodeNormalizer($jsonEncodeOptions);

$normalized = $normalizer->normalize($json);
```

The normalized version will now be encoded with `$jsonEncodeOptions`.

:bulb: For reference, see [`json_encode()`](http://php.net/manual/en/function.json-encode.php)
and the corresponding [JSON constants](http://php.net/manual/en/json.constants.php).

### `NoFinalNewLineNormalizer`

If you want to ensure that a JSON file does not have a final new line, you can use the `FinalNewLineNormalizer`.
Expand Down
53 changes: 53 additions & 0 deletions src/JsonEncodeNormalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2018 Andreas Möller.
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*
* @see https://github.com/localheinz/json-normalizer
*/

namespace Localheinz\Json\Normalizer;

final class JsonEncodeNormalizer implements NormalizerInterface
{
/**
* @var int
*/
private $jsonEncodeOptions;

/**
* @param int $jsonEncodeOptions
*
* @throws \InvalidArgumentException
*/
public function __construct(int $jsonEncodeOptions)
{
if (0 > $jsonEncodeOptions) {
throw new \InvalidArgumentException(\sprintf(
'"%s" is not valid options for json_encode().',
$jsonEncodeOptions
));
}
$this->jsonEncodeOptions = $jsonEncodeOptions;
}

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
));
}

return \json_encode(
\json_decode($json),
$this->jsonEncodeOptions
);
}
}
117 changes: 117 additions & 0 deletions test/Unit/JsonEncodeNormalizerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2018 Andreas Möller.
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*
* @see https://github.com/localheinz/json-normalizer
*/

namespace Localheinz\Json\Normalizer\Test\Unit;

use Localheinz\Json\Normalizer\JsonEncodeNormalizer;

final class JsonEncodeNormalizerTest extends AbstractNormalizerTestCase
{
public function testConstructorRejectsInvalidJsonEncodeOptions()
{
$jsonEncodeOptions = -1;

$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage(\sprintf(
'"%s" is not valid options for json_encode().',
$jsonEncodeOptions
));

new JsonEncodeNormalizer($jsonEncodeOptions);
}

/**
* @dataProvider providerJsonEncodeOptions
*
* @param int $jsonEncodeOptions
*/
public function testNormalizeDecodesAndEncodesJsonWithJsonEncodeOptions(int $jsonEncodeOptions)
{
$json = <<<'JSON'
{
"name": "Andreas M\u00f6ller",
"url": "https:\/\/github.com\/localheinz\/json-normalizer",
"string-apostroph": "'",
"string-numeric": "9000",
"string-quote": "\"",
"string-tag": "<p>"
}
JSON;
$normalizer = new JsonEncodeNormalizer($jsonEncodeOptions);

$encoded = \json_encode(
\json_decode($json),
$jsonEncodeOptions
);

$this->assertSame($encoded, $normalizer->normalize($json));
}

public function providerJsonEncodeOptions(): \Generator
{
/**
* Could add more, but the idea counts.
*/
$jsonEncodeFlags = [
JSON_HEX_APOS,
JSON_HEX_QUOT,
JSON_HEX_TAG,
JSON_NUMERIC_CHECK,
JSON_UNESCAPED_SLASHES,
JSON_UNESCAPED_UNICODE,
];

$combinations = $this->combinations($jsonEncodeFlags);

foreach ($combinations as $combination) {
$jsonEncodeOptions = \array_reduce(
$combination,
function (int $jsonEncodeFlag, int $jsonEncodeOptions) {
$jsonEncodeOptions |= $jsonEncodeFlag;

return $jsonEncodeOptions;
},
0
);

yield [
$jsonEncodeOptions,
];
}
}

/**
* @see https://docstore.mik.ua/orelly/webprog/pcook/ch04_25.htm
*
* @param array $elements
*
* @return array
*/
private function combinations(array $elements): array
{
$combinations = [[]];

foreach ($elements as $element) {
foreach ($combinations as $combination) {
$combinations[] = \array_merge(
[
$element,
],
$combination
);
}
}

return $combinations;
}
}

0 comments on commit ddfc7cc

Please sign in to comment.