Giter VIP home page Giter VIP logo

ergebnis-json-normalizer's Introduction

json-normalizer

Integrate Merge Release Renew Triage Update

Code Coverage Type Coverage

Latest Stable Version Total Downloads Monthly Downloads

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:

💡 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:

Vendor\Composer\BinNormalizer

When composer.json contains an array of scripts in the bin section, the Vendor\Composer\BinNormalizer 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\ConfigHashNormalizer

When composer.json contains configuration in the config section, the Vendor\Composer\ConfigHashNormalizer will sort the content of these sections by key in ascending order.

💡 Find out more about the config 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 version constraints are trimmed

     {
       "homepage": "https://getcomposer.org/doc/articles/versions.md#version-range",
       "require": {
    -    "php": " ^8.2 "
    +    "php": "^8.2"
     }
  • version constraints separated by a space ( ) or comma (,) - treated as a logical and - are separated by a space ( ) instead

     {
       "homepage": "https://getcomposer.org/doc/articles/versions.md#version-range",
       "require": {
    -    "foo/bar": "1.2.3,2.3.4",
    -    "foo/baz": "2.3.4   3.4.5"
    +    "foo/bar": "1.2.3 2.3.4",
    +    "foo/baz": "2.3.4 3.4.5"
     }
  • version constraints separated by a single- (|) or double-pipe (||) and any number of spaces before and after - treated as a logical or - are separated by a double pipe with a single space before and after (||)

     {
       "homepage": "https://getcomposer.org/doc/articles/versions.md#version-range",
       "require": {
    -    "php": "^8.1|^8.2",
    -    "foo/bar": "^1.2.3  ||  ^2.3.4"
    +    "php": "^8.1 || ^8.2",
    +    "foo/bar": "^1.2.3 || ^2.3.4"
     }
  • hyphenated version constraints separated by dash (-) and any positive number of spaces before and after are separated by a dash with a single space before and after (-)

     {
       "homepage": "https://getcomposer.org/doc/articles/versions.md#hyphenated-version-range-",
       "require": {
    -    "foo/bar": "1.2.3  -  2.3.4"
    +    "foo/bar": "1.2.3 - 2.3.4"
     }
  • duplicate constraints are removed

     {
       "homepage": "https://getcomposer.org/doc/articles/versions.md#version-range",
       "require": {
    -    "foo/bar": "^1.0 || ^1.0 || ^2.0"
    +    "foo/bar": "^1.0 || ^2.0"
     }
  • overlapping constraints are removed

     {
       "homepage": "https://getcomposer.org/doc/articles/versions.md#version-range",
       "require": {
    -    "foo/bar": "^1.0 || ^1.1 || ^2.0"
    +    "foo/bar": "^1.0 || ^2.0"
     }
  • version numbers are sorted in ascending order

     {
       "homepage": "https://getcomposer.org/doc/articles/versions.md#version-range",
       "require": {
    -    "foo/bar": "^2.0 || ^1.4"
    +    "foo/bar": "^1.4 || ^2.0"
     }

💡 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!

ergebnis-json-normalizer's People

Contributors

backendtea avatar dependabot-preview[bot] avatar dependabot[bot] avatar ergebnis-bot avatar fredden avatar localheinz avatar mimmi20 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.