Basel Shishani
Basel Shishani

Reputation: 8177

A JSON parser for PHP that supports comments

Can anyone suggest a JSON parser that allows any kind of comments, with PHP bindings - need the comments badly for config files but json_decode doesn't support them.

(I am aware of: 1. other format such as YAML, 2. comments are not part of the standard)

Update:

Why don't we use:

Upvotes: 16

Views: 5212

Answers (6)

Eaten by a Grue
Eaten by a Grue

Reputation: 22931

If you don't need inline or multi-line comments and only use // style comments on lines by themselves - here's a reliable way to strip them without using regex:

settings.json:

// global settings for my app
{
    "MAIN_DIR" : "/path/to/dir/",
    "DB_NAME"  : "my_app",

    // auth keys for example.com
    "ID"     : "123ABC",
    "SECRET" : "1834966f74fbc8b672296a9356eec43f"
}

read_settings.php

$lines = file('settings.json');
$lines = array_map('trim', $lines);
$lines = array_filter($lines, fn($v) => strpos($v, '//') !== 0); 
$settings = json_decode(implode(PHP_EOL, $lines), true);

Upvotes: 0

Alexander Shostak
Alexander Shostak

Reputation: 722

You can use the following function to decode commented json:

function json_decode_commented($data, $assoc = false, $maxDepth = 512, $opts = 0) {
  $data = preg_replace('~
    (" (?:\\\\. | [^"])*+ ") | \# [^\v]*+ | // [^\v]*+ | /\* .*? \*/
  ~xs', '$1', $data);

  return json_decode($data, $assoc, $maxDepth, $opts);
}

It supports all PHP-style comments: /*, #, //. String values are preserved as is.

Upvotes: 10

aross
aross

Reputation: 3606

I'm surprised nobody mentioned json5

{
  // comments
  unquoted: 'and you can quote me on that',
  singleQuotes: 'I can use "double quotes" here',
  lineBreaks: "Look, Mom! \
No \\n's!",
  hexadecimal: 0xdecaf,
  leadingDecimalPoint: .8675309, andTrailing: 8675309.,
  positiveSign: +1,
  trailingComma: 'in objects', andIn: ['arrays',],
  "backwardsCompatible": "with JSON",
}

Upvotes: 4

Timo Tijhof
Timo Tijhof

Reputation: 10269

YAML

If you need portability and don't want any pre-processing or non-standard syntax, then YAML is probably the way to go. Though, beware of the dangers and caveats of YAML.

Most, if not all, of JSON is compatible with YAML (YAML is a superset of JSON), and it supports comments. So the initial switch is easy.

JSON with comments

I recently needed to migrate from INI files in PHP to something that has support for integers and booleans, but still supported comments as well.

JSON seemed like a good format, except for supporting comments. If you want to make this work, you don't need a whole custom JSON parser. It can be made to work with simple wrapper that strips the comments uses the native json_decode after that. (This works for sane content that trusted people author. If you allow crazy inputs there is probably a way to break this.)

Code from github.com/countervandalism/stillalive, with the regex from @makaveli_lcf:

class JsonUtil {
    /**
     * From https://stackoverflow.com/a/10252511/319266
     * @return array|false
     */
    public static function load( $filename ) {
        $contents = @file_get_contents( $filename );
        if ( $contents === false ) {
            return false;
        }
        return json_decode( self::stripComments( $contents ), true );
    }
    /**
     * From https://stackoverflow.com/a/10252511/319266
     * @param string $str
     * @return string
     */
    protected static function stripComments( $str ) {
        return preg_replace( '![ \t]*//.*[ \t]*[\r\n]!', '', $str );
    }
}

Upvotes: 12

Sinus tentaclemonster
Sinus tentaclemonster

Reputation: 538

Another option is to allow your users to insert comments as unused fields in the JSON structure:

{
  "color": "red",
  "color//": "may be red, green or blue"
}

If you only use your JSON for input, and it's never machine-saved, you could abuse the format to use the same field repeatedly, incidentally achieving a near-wipe of the comments when parsing (as usually only the first or the last value of a field will be retained in a parsed structure):

{
  "color": "red",      "//":"may be red, green or blue",
  "shape": "circle",   "//":"use circle, square or triangle",
  "timeout": 5,        "//":"timeout in seconds; default is 10"
}

Upvotes: 2

ThiefMaster
ThiefMaster

Reputation: 318468

Comments are not part of JSON, so a "JSON parser" is not required to accept comments..

I'd use YAML. Even if parsing is slightly slower (PHP has a native JSON parser but no native YAML parser) it's probably neglectible and if it's not, you can always cache the parsed object. Besides that, since the PHP JSON parser does not support comments you'd have to use a non-native one, i.e. it most likely wouldn't be faster than the YAML parser (assuming both are well-written)

Upvotes: 1

Related Questions