JS проверяет JSON на наличие дубликатов ключей перед загрузкой? - PullRequest
0 голосов
/ 07 июля 2019

В настоящее время я загружаю текстовый файл, который содержит данные в формате JSON. Я хочу проверить это до анализа.

В данный момент я загружаю его, используя следующее:

$.getJSON('dataFile', function(data) {
}

Это работает, но я не могу проверить его на наличие дубликатов ключей после его загрузки, так как дубликатов ключей теперь не существует.

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

Есть ли другой способ загрузить его, чтобы я мог проверить ключи перед анализом?

Спасибо

1 Ответ

1 голос
/ 07 июля 2019

Как вы написали:

В текстах JSON не должно быть дубликатов ключей согласно RFC 7159

и, следовательно, дубликаты ключей будут заменены при синтаксическом анализе JSON на JSON.parse() (что и делает JQuery за кулисами). Это означает, что вам нужно проверить дубликаты ключей перед этапом JSON-разбора.

У меня нет чистого решения, но в зависимости от ваших потребностей в валидации этого может быть достаточно:

Вы можете в основном использовать что-то вроде this , чтобы минимизировать ваши входящие данные JSON (из запроса) и сохранить их в переменной, затем вызвать JSON.parse() для данных ответа, а также преобразовать в строку и минимизировать это. а затем сравнить два для равенства строк. Если они не равны, вы могли бы вычесть, что были дублирующиеся ключи, хотя не то, какие именно ключи ... но, как я уже сказал, если вы просто хотите выдать ошибку, если обнаружены дублирующие ключи любого типа, этого будет достаточно.

/*! JSON.minify()
    v0.1 (c) Kyle Simpson
    MIT License
*/
/**
 * @name minify.json.js
 * @author Kei Funagayama <kei.topaz@gmail.com
 * @overview JSON.minify
 */

/**
 * @namespace JSON
 */
(function(global){
    'use strict';

    /**
     * @function
     * @memberof JSON
     * @param {Object} Transformed data. format) json-like
     * @return {String}
     *
     * @example
     * var json = { // hoge
     *     "foo": "bar",// this is cool
     *     "bar": [
     *         "baz", "bum", "zam"   // this is cool
     *     ]
     * } // hoge
     *
     */
    var minify = function (json) {

        var tokenizer = /"|(\/\*)|(\*\/)|(\/\/)|\n|\r|\[|]/g,
            in_string = false,
            in_multiline_comment = false,
            in_singleline_comment = false,
            tmp, tmp2, new_str = [], ns = 0, from = 0, lc, rc
        ;

        tokenizer.lastIndex = 0;

        while ( tmp = tokenizer.exec(json) ) {
            lc = RegExp.leftContext;
            rc = RegExp.rightContext;
            if (!in_multiline_comment && !in_singleline_comment) {
                tmp2 = lc.substring(from);
                if (!in_string) {
                    tmp2 = tmp2.replace(/(\n|\r|\s)*/g,"");
                }
                new_str[ns++] = tmp2;
            }
            from = tokenizer.lastIndex;

            if (tmp[0] === "\"" && !in_multiline_comment && !in_singleline_comment) {
                tmp2 = lc.match(/(\\)*$/);
                if (!in_string || !tmp2 || (tmp2[0].length % 2) === 0) {    // start of string with ", or unescaped " character found to end string
                    in_string = !in_string;
                }
                from--; // include " character in next catch
                rc = json.substring(from);
            }
            else if (tmp[0] === "/*" && !in_string && !in_multiline_comment && !in_singleline_comment) {
                in_multiline_comment = true;
            }
            else if (tmp[0] === "*/" && !in_string && in_multiline_comment && !in_singleline_comment) {
                in_multiline_comment = false;
            }
            else if (tmp[0] === "//" && !in_string && !in_multiline_comment && !in_singleline_comment) {
                in_singleline_comment = true;
            }
            else if ((tmp[0] === "\n" || tmp[0] === "\r") && !in_string && !in_multiline_comment && in_singleline_comment) {
                in_singleline_comment = false;
            }
            else if (!in_multiline_comment && !in_singleline_comment && !(/\n|\r|\s/.test(tmp[0]))) {
                new_str[ns++] = tmp[0];
            }
        }
        new_str[ns++] = rc;
        return new_str.join("");
    };

    if (typeof module !== 'undefined' && module.exports) {
        // node
        module.exports = minify;
        JSON.minify = minify;
    } else {
        // others, export global
        if (typeof global.JSON === "undefined" || !global.JSON) {
            global.JSON = {};
        }
        global.JSON.minify = minify;
    }
})(this);


$.ajax({
  url: 'https://jsonplaceholder.typicode.com/users',
  // make sure jQuery doesn't try to be smart and parse the JSON already
  dataType: 'text'
}).done(function(data) {
  
  var raw = JSON.minify(data);
  var parsed = JSON.minify(JSON.stringify(JSON.parse(data)));
  
  if ( raw === parsed ) {
    console.log('No duplicate keys found');
  } else {
    console.log('Possible duplicate keys!');
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Если вам действительно нужно пойти дальше и выяснить, какой ключ является дубликатом, вы можете запустить какой-нибудь метод string-diff, чтобы найти разницу между raw и parsed и продолжить оттуда.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...