Парсер JSON для PHP, который поддерживает комментарии

Может ли кто-нибудь предложить парсер JSON, который позволяет любые комментарии, с привязками PHP, - плохо нуждается в комментариях для файлов конфигурации, но json_decode не поддерживает их.

(Я знаю: 1. другой формат, такой как YAML, 2. комментарии не являются частью стандарта)

Update:

Почему мы не используем:

  • YAML: тесты показывают это медленнее - и мы можем отправить данные по проводу - не уверен, что YAML лучше для этого.

  • XML: слишком многословный - простое редактирование человека - это требование. И нет необходимости в расширенных функциях XML.

  • INI: в данных есть иерархия и вложенность переменной глубины. И нам нужен вездесущий формат, поскольку данные могут быть распространены с приложениями или работать с приложениями на других языках.

  • Предварительная обработка: данные могут предоставляться пользователями и делиться ими, что очень сложно предъявить требование предварительной обработки перед добавлением данных в приложение.

Ответ 1

Если вам нужна мобильность и вы не хотите, чтобы какая-либо предварительная обработка исправляла нестандартные компоненты, тогда YAML - это, вероятно, верный путь.

Большинство, если не все, JSON совместимы с YAML (YAML - это расширенный набор JSON) и поддерживают комментарии.

Для недавнего проекта я почувствовал необходимость отойти от .ini для нашего файла "настроек по умолчанию" - чтобы нам больше не приходилось преобразовывать некоторые строки в целые или логические значения впоследствии (поскольку parse_ini_file анализирует значения как строки, foo=1 или foo=true оба являются строковыми значениями).

JSON показался мне хорошим форматом, но он не поддерживал комментарии. Однако, если вы хотите, чтобы это работало, я бы рекомендовал не реализовывать (или не использовать) отдельный JSON-анализатор вообще. Я создал простую функцию-обертку, которая удаляет комментарии с помощью регулярного выражения, а затем использует собственный json_decode.

Пример из https://github.com/countervandalism/stillalive/blob/v2018.11/src/Util.php#L21-L41:

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

Ответ 2

Вы можете использовать следующую функцию для декодирования комментария json:

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

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

Он поддерживает все комментарии в стиле PHP:/*, #,//. Значения строк сохраняются как есть.

Ответ 3

Комментарии не являются частью JSON, поэтому "JSON parser" не требуется принимать комментарии.

Я бы использовал YAML. Даже если синтаксический анализ немного медленнее (у PHP есть собственный JSON-анализатор, но нет собственного анализатора YAML), он, вероятно, пренебрежимо, и если это не так, вы всегда можете кэшировать проанализированный объект. Кроме того, поскольку парсер PHP JSON не поддерживает комментарии, вам придется использовать неродный, т.е. Он скорее всего не будет быстрее, чем парсер YAML (при условии, что оба они хорошо написаны)

Ответ 4

Другой вариант - разрешить пользователям вставлять комментарии в виде неиспользуемых полей в структуре JSON:

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

Если вы используете только JSON для ввода, и он никогда не сохраняется на компьютере, вы можете злоупотребить форматом для повторного использования одного и того же поля, что может привести к почти полной очистке комментариев при разборе (как правило, только первое или последнее значение поле будет сохранено в разобранной структуре):

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