Skip to content

Enhance JSON config files validation #316

@llaville

Description

@llaville

When we write or update a captainhook.json configuration files, sometimes we may have syntax errors.

Currently, it's a bit hard to find where is origin of error.

Image

I suggest to add https://github.com/Seldaek/jsonlint implementation like it is with Composer 2.9 (code)

Code look like (partial class implementation)

<?php

namespace CaptainHook\App\Storage\File;

use CaptainHook\App\Storage\File;
use RuntimeException;
use stdClass;
use Seld\JsonLint\JsonParser;
use Seld\JsonLint\ParsingException;

final class Json extends File
{
    public function read(bool $assoc = false): array|stdClass|null
    {
        $jsonContent = parent::read();
        $json = json_decode($jsonContent, $assoc);
        if (null === $json) {
            self::validateSyntax($jsonContent);
        }
        return $json;
    }

    // CREDITS: code from Composer https://github.com/composer/composer/blob/2.9/src/Composer/Json/JsonFile.php#L376
    private static function validateSyntax(string $json, ?string $file = null): bool
    {
        $parser = new JsonParser();
        $result = $parser->lint($json);
        if (null === $result) {
            if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
                if ($file === null) {
                    throw new \UnexpectedValueException('The input is not UTF-8, could not parse as JSON');
                } else {
                    throw new \UnexpectedValueException('"' . $file . '" is not UTF-8, could not parse as JSON');
                }
            }

            return true;
        }

        if ($file === null) {
            throw new ParsingException(
                'The input does not contain valid JSON' . "\n" . $result->getMessage(),
                $result->getDetails()
            );
        } else {
            throw new ParsingException(
                '"' . $file . '" does not contain valid JSON' . "\n" . $result->getMessage(),
                $result->getDetails()
            );
        }
    }
}

It will give something like

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions