ergebnis / json-normalizer
Provides generic and vendor-specific normalizers for normalizing JSON documents.
Installs: 9 044 306
Dependents: 7
Suggesters: 0
Security: 0
Stars: 65
Watchers: 3
Forks: 2
Open Issues: 5
Requires
- php: ^7.4 || ^8.0
- ext-json: *
- ergebnis/json-pointer: ^3.1.0
- ergebnis/json-printer: ^3.2.0
- ergebnis/json-schema-validator: ^3.1.0
- justinrainbow/json-schema: ^5.2.12
Requires (Dev)
- ergebnis/data-provider: ^1.2.0
- ergebnis/license: ^1.2.0
- ergebnis/php-cs-fixer-config: ^4.6.0
- fakerphp/faker: ^1.20.0
- infection/infection: ~0.26.6
- phpunit/phpunit: ^9.5.21
- psalm/plugin-phpunit: ~0.17.0
- vimeo/psalm: ^4.26
- dev-main
- 3.0.0
- 2.2.0
- 2.1.0
- 2.0.0
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
- 0.14.1
- 0.14.0
- 0.13.1
- 0.13.0
- 0.12.0
- 0.11.0
- 0.10.1
- 0.10.0
- 0.9.0
- 0.8.0
- 0.7.0
- 0.6.0
- 0.5.2
- 0.5.1
- 0.5.0
- 0.4.0
- 0.3.0
- 0.2.0
- 0.1.0
- dev-dependabot/composer/ergebnis/php-cs-fixer-config-5.3.0
- dev-dependabot/composer/phpunit/phpunit-9.6.3
- dev-dependabot/composer/infection/infection-0.26.19
- dev-feature/diff
- dev-feature/remaining
This package is auto-updated.
Last update: 2023-02-06 20:10:45 UTC
README
Provides generic and vendor-specific normalizers for normalizing JSON documents.
Installation
Run
composer require ergebnis/json-normalizer
Usage
Generic normalizers
This package comes with the following generic normalizers:
Ergebnis\Json\Normalizer\CallableNormalizer
Ergebnis\Json\Normalizer\ChainNormalizer
Ergebnis\Json\Normalizer\FormatNormalizer
Ergebnis\Json\Normalizer\IndentNormalizer
Ergebnis\Json\Normalizer\JsonEncodeNormalizer
Ergebnis\Json\Normalizer\SchemaNormalizer
Ergebnis\Json\Normalizer\WithFinalNewLineNormalizer
Ergebnis\Json\Normalizer\WithoutFinalNewLineNormalizer
💡 All of these normalizers implement the Ergebnis\Json\Normalizer\Normalizer
.
CallableNormalizer
When you want to normalize a JSON file with a callable
, you can use the CallableNormalizer
.
<?php declare(strict_types=1); use Ergebnis\Json\Json; use Ergebnis\Json\Normalizer; $encoded = <<<'JSON' { "name": "Andreas Möller", "url": "https://localheinz.com" } JSON; $json = Json::fromString($encoded); $callable = function (Json $json): Json { $decoded = $json->decoded(); foreach (get_object_vars($decoded) as $name => $value) { if ('https://localheinz.com' !== $value) { continue; } $decoded->{$name} .= '/open-source/'; } return Json::fromString(json_encode($decoded)); }; $normalizer = new Normalizer\CallableNormalizer($callable); $normalized = $normalizer->normalize($json);
The normalized version will now have the callable applied to it.
ChainNormalizer
When you want to apply multiple normalizers in a chain, you can use the ChainNormalizer
.
<?php declare(strict_types=1); use Ergebnis\Json\Json; use Ergebnis\Json\Normalizer; use Ergebnis\Json\Printer; $encoded = <<<'JSON' { "name": "Andreas Möller", "url": "https://localheinz.com" } JSON; $json = Json::fromString($encoded); $indent = Normalizer\Format\Indent::fromString(' '); $jsonEncodeOptions = Normalizer\Format\JsonEncodeOptions::fromInt(JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $normalizer = new Normalizer\ChainNormalizer( new Normalizer\JsonEncodeNormalizer($jsonEncodeOptions), new Normalizer\IndentNormalizer( $indent, new Printer\Printer() ), new Normalizer\WithFinalNewLineNormalizer() ); $normalized = $normalizer->normalize($json);
The normalized version will now contain the result of applying all normalizers in a chain, one after another.
💡 Be careful with the order of the normalizers, as one normalizer might override changes a previous normalizer applied.
FormatNormalizer
When you want to normalize a JSON file with a formatting, you can use the FormatNormalizer
.
<?php declare(strict_types=1); use Ergebnis\Json\Json; use Ergebnis\Json\Normalizer; use Ergebnis\Json\Printer; $encoded = <<<'JSON' { "name": "Andreas Möller", "emoji": "🤓", "url": "https://localheinz.com" } JSON; $json = Json::fromString($encoded); $format = Normalizer\Format\Format::create( Normalizer\Format\Indent::fromString(' '), Normalizer\Format\JsonEncodeOptions::fromInt(JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), Normalizer\Format\NewLine::fromString("\r\n") true ); $normalizer = new Normalizer\FormatNormalizer( new Printer\Printer(), $format, ); $normalized = $normalizer->normalize($json);
The normalized version will now have formatting applied according to $format
.
IndentNormalizer
When you need to adjust the indentation of a JSON file, you can use the IndentNormalizer
.
<?php declare(strict_types=1); use Ergebnis\Json\Json; use Ergebnis\Json\Normalizer; use Ergebnis\Json\Printer; $encoded = <<<'JSON' { "name": "Andreas Möller", "url": "https://localheinz.com" } JSON; $json = Json::fromString($encoded); $indent = Normalizer\Format\Indent::fromString(' '); $normalizer = new Normalizer\IndentNormalizer( $indent, new Printer\Printer() ); $normalized = $normalizer->normalize($json);
The normalized version will now be indented with 2 spaces.
JsonEncodeNormalizer
When you need to adjust the encoding of a JSON file, you can use the JsonEncodeNormalizer
.
<?php declare(strict_types=1); use Ergebnis\Json\Json; use Ergebnis\Json\Normalizer; $encoded = <<<'JSON' { "name": "Andreas M\u00f6ller", "url": "https:\/\/localheinz.com" } JSON; $json = Json::fromString($encoded); $jsonEncodeOptions = Normalizer\Format\JsonEncodeOptions::fromInt(JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); $normalizer = new Normalizer\JsonEncodeNormalizer($jsonEncodeOptions); $normalized = $normalizer->normalize($json);
The normalized version will now be encoded with $jsonEncodeOptions
.
💡 For reference, see json_encode()
and the corresponding JSON constants.
SchemaNormalizer
When you want to rebuild a JSON file according to a JSON schema, you can use the SchemaNormalizer
.
Let's assume the following schema
{ "type": "object", "additionalProperties": true, "properties": { "name" : { "type" : "string" }, "role" : { "type" : "string" } } }
exists at /schema/example.json
.
<?php declare(strict_types=1); use Ergebnis\Json\Normalizer; use Ergebnis\Json\Pointer; use Ergebnis\Json\SchemaValidator; use JsonSchema\SchemaStorage; $encoded = <<<'JSON' { "url": "https://localheinz.com", "name": "Andreas Möller", "open-source-projects": { "ergebnis/data-provider": { "downloads": { "total": 2, "monthly": 1 } }, "ergebnis/composer-normalize": { "downloads": { "total": 5, "monthly": 2 } } } } JSON; $json = Json::fromString($encoded); $normalizer = new Normalizer\SchemaNormalizer( 'file:///schema/example.json', new SchemaStorage(), new SchemaValidator\SchemaValidator(), Pointer\Specification::never() ); $normalized = $normalizer->normalize($json);
The normalized version will now be structured according to the JSON schema (in this simple case, properties will be reordered as found in the schema and additional properties will be ordered by name). Internally, the SchemaNormalizer
uses justinrainbow/json-schema
to resolve schemas, as well as to ensure (before and after normalization) that the JSON document is valid.
If you have properties that you do not want to be reordered, you can use a Pointer\Specification
to specify which properties should not be reordered.
<?php declare(strict_types=1); use Ergebnis\Json\Normalizer; use Ergebnis\Json\Pointer; use Ergebnis\Json\SchemaValidator; use JsonSchema\SchemaStorage; $encoded = <<<'JSON' { "url": "https://localheinz.com", "name": "Andreas Möller", "open-source-projects": { "ergebnis/data-provider": { "downloads": { "total": 2, "monthly": 1 } }, "ergebnis/composer-normalize": { "downloads": { "total": 5, "monthly": 2 } } } } JSON; $json = Json::fromString($encoded); $normalizer = new Normalizer\SchemaNormalizer( 'file:///schema/example.json', new SchemaStorage(), new SchemaValidator\SchemaValidator(), Pointer\Specification::equals(Pointer\JsonPointer::fromJsonString('/open-source-projects')) ); $normalized = $normalizer->normalize($json);
💡 For more information about JSON schema, visit json-schema.org.
WithFinalNewLineNormalizer
When you want to ensure that a JSON file has a single final new line, you can use the WithFinalNewLineNormalizer
.
<?php declare(strict_types=1); use Ergebnis\Json\Normalizer; $encoded = <<<'JSON' { "name": "Andreas Möller", "url": "https://localheinz.com" } JSON; $json = Json::fromString($encoded); $normalizer = new Normalizer\WithFinalNewLineNormalizer(); $normalized = $normalizer->normalize($json);
The normalized version will now have a single final new line.
WithoutFinalNewLineNormalizer
When you want to ensure that a JSON file does not have a final new line, you can use the WithoutFinalNewLineNormalizer
.
<?php declare(strict_types=1); use Ergebnis\Json\Normalizer; $encoded = <<<'JSON' { "name": "Andreas Möller", "url": "https://localheinz.com" } JSON; $json = Json::fromString($encoded); $normalizer = new Normalizer\WithoutFinalNewLineNormalizer(); $normalized = $normalizer->normalize($json);
The normalized version will now not have a final new line or any whitespace at the end.
Vendor-specific normalizers
This package comes with the following vendor-specific normalizers:
Vendor\Composer\ComposerJsonNormalizer
The Vendor\Composer\ComposerJsonNormalizer
can be used to normalize a composer.json
file according to its underlying JSON schema.
It composes the following normalizers:
Ergebnis\Composer\Json\Normalizer\Vendor\Composer\PackageHashNormalizer
Ergebnis\Composer\Json\Normalizer\Vendor\Composer\VersionConstraintNormalizer
Ergebnis\Composer\Json\Normalizer\Vendor\WithFinalNewLineNormalizer
bin
When composer.json
contains an array of scripts in the bin
section, the Vendor\Composer\ComposerJsonNormalizer
will sort the elements of the bin
section by value in ascending order.
💡 Find out more about the bin
section at Composer: The composer.json schema.
Vendor\Composer\PackageHashNormalizer
When composer.json
contains any configuration in the
conflict
provide
replace
require
require-dev
suggest
sections, the Vendor\Composer\PackageHashNormalizer
will sort the packages in these sections.
💡 This transfers the behaviour from using the --sort-packages
or sort-packages
configuration flag in require
and require-dev
to other sections. Find out more about the --sort-packages
flag and configuration at Composer: Config and Composer: Command Line Interface / Commands.
Vendor\Composer\VersionConstraintNormalizer
When composer.json
contains version constraints in the
conflict
provide
replace
require
require-dev
sections, the Vendor\Composer\VersionConstraintNormalizer
will ensure that
- all constraints are trimmed
- *and- constraints are separated by a single space (
,
) - *or- constraints are separated by double-pipe with a single space before and after (
||
) - *range- constraints are separated by a single space (
💡 Find out more about version constraints at Composer: Version and Constraints.
Changelog
Please have a look at CHANGELOG.md
.
Contributing
Please have a look at CONTRIBUTING.md
.
Code of Conduct
Please have a look at CODE_OF_CONDUCT.md
.
License
This package is licensed using the MIT License.
Please have a look at LICENSE.md
.
Credits
The algorithm for sorting packages in the Vendor\Composer\PackageHashNormalizer
has been adopted from Composer\Json\JsonManipulator::sortPackages()
(originally licensed under MIT by Nils Adermann and Jordi Boggiano), which I initially contributed to composer/composer
with composer/composer#3549
and composer/composer#3872
.
Curious what I am up to?
Follow me on Twitter!