rfc:json_validate

This is an old revision of the document!


PHP RFC: json_validate

Introduction

This RFC introduces a new function called json_validate() to validate if an string contains a valid json.

Most userland implementations use json_decode() which by design generates a ZVAL(object/array/etc.) while parsing the string, ergo using memory and processing that could be save.

Proposal

Description

json_validate(string $json, int $depth = 512, int $flags = 0): bool

Parameters

json

The json string being analyzed.

This function only works with UTF-8 encoded strings.

Note:

PHP implements a superset of JSON as specified in the original » RFC 7159.

depth

Maximum nesting depth of the structure being decoded.

flags

Bitmask of JSON_INVALID_UTF8_IGNORE. The behavior of this constant is described on the JSON constants page.

Return values

Returns true if the string passed contains a valid json, otherwise returns false.

Examples

1. Validate a valid json-string

var_dump(json_validate('{ "test": { "foo": "bar" } }'));

Result will be

bool(true)

2. Validate an invalid json-string

var_dump(json_validate('{ "": "": "" } }'));

Result will be

bool(false)

Fundaments/Reasons

Disadvantages of using json_decode to only validate a json-string

By design, json_decode() generates an object/array while parsing the string, ergo using memory and processing for it, that is not needed if the only thing to discover is if a string contains a valid json.

Disadvantages of using regex

Using a regex for this task forces different, error-prone, hard to maintain, implementations.

Needs from major projects and developers

In the “References” section, there is a list of major open-source php projects that could benefit with this new function.

Also in the mentioned section a link to one of the most popular StackOverflow questions is provided, which somehow reflects the need from our developers to have a feature like this included.

Please check the “References” section.

Complexity added in the core

At the moment, there is a JSON parser in the core, used by json_decode to do its job, so there is no need to write a new JSON parser for this RFC; the proposed function will use the existing JSON parser exclusively to parse an string without generating any object/array in memory for it.

Backward Incompatible Changes

None, as this is a new function only.

json_validate will no longer be available as a function name.

Proposed PHP Version(s)

next PHP 8.x

RFC Impact

This RFC has no impact on SAPIs, existing extensions, Opcache, etc.

Open Issues

- No open issues

Future Scope

- (To be defined by future discussions if needed)

Proposed Voting Choices

- (To be defined)

Implementation

References

Major Open-Source projects that will benefit out of this

Symfony Framework

class JsonValidator extends ConstraintValidator

Laravel Framework

    public function validateJson($attribute, $value)
    {
        if (is_array($value)) {
            return false;
        }
 
        if (! is_scalar($value) && ! is_null($value) && ! method_exists($value, '__toString')) {
            return false;
        }
 
        json_decode($value);
 
        return json_last_error() === JSON_ERROR_NONE;
    }

Laravel Framework

    public static function isJson($value)
    {

Magento

    protected function isValidJsonValue($value)
    {
        if (in_array($value, ['null', 'false', '0', '""', '[]'])
            || (json_decode($value) !== null && json_last_error() === JSON_ERROR_NONE)
        ) {
            return true;
        }
        //JSON last error reset
        json_encode([]);
        return false;
    }

Magento

    public function isValid($string)
    {
        if ($string !== false && $string !== null && $string !== '') {
            json_decode($string);
            if (json_last_error() === JSON_ERROR_NONE) {
                return true;
            }
        }
        return false;
    }

getgrav

    public static function validateJson($value, $params)
    {
        return (bool) (@json_decode($value));
    }

Respect / Validation

final class Json extends AbstractRule
{
    /**
     * {@inheritDoc}
     */
    public function validate($input): bool
    {
        if (!is_string($input) || $input === '') {
            return false;
        }
 
        json_decode($input);
 
        return json_last_error() === JSON_ERROR_NONE;
    }
}

Respect / Validation

final class Json extends AbstractRule
{
    /**
     * {@inheritDoc}
     */
    public function validate($input): bool
    {
        if (!is_string($input) || $input === '') {
            return false;
        }
 
        json_decode($input);
 
        return json_last_error() === JSON_ERROR_NONE;
    }
}

Prestashop

    public static function isJson($string)
    {
        json_decode($string);
 
        return json_last_error() == JSON_ERROR_NONE;
    }

Wordpress CLI

function is_json( $argument, $ignore_scalars = true ) {
    if ( ! is_string( $argument ) || '' === $argument ) {
        return false;
    }
 
    if ( $ignore_scalars && ! in_array( $argument[0], [ '{', '[' ], true ) ) {
        return false;
    }
 
    json_decode( $argument, $assoc = true );
 
    return json_last_error() === JSON_ERROR_NONE;
}

JOOMLA CMS

if (\is_string($value)) {
    json_decode($value); //<------ HERE
 
    // Check if value is a valid JSON string.
    if ($value !== '' && json_last_error() !== JSON_ERROR_NONE) {
        /**
         * If the value is not empty and is not a valid JSON string,
         * it is most likely a custom field created in Joomla 3 and
         * the value is a string that contains the file name.
        */
        if (is_file(JPATH_ROOT . '/' . $value)) {
            $value = '{"imagefile":"' . $value . '","alt_text":""}';
        } else {
            $value = '';
        }
    }

In PHP, this question is one of the most high ranked questions related to json && php in stackoverflow, “Fastest way to check if a string is JSON in PHP?”. The question

Viewed 484k times. The ranking

Person asking how to do exactly this, also providing a real use case; eventhough in python, the programming language is not important. In Python

Someone has also doing exactly this , in JAVA. In Java

Open questions

Should we remove the capability of json_validate() to use the flag JSON_THROW_ON_ERROR? During the discussion in the inernals mailing list the user Rowan Tommins rowan.collins@gmail.com raised this concern.

rfc/json_validate.1661585297.txt.gz · Last modified: 2022/08/27 07:28 by juan_morales