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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions