Чтобы отфильтровать недостающие ключи после сравнения двух json объектов (используется фильтр js, но он не работает для всех сценариев ios) - PullRequest
0 голосов
/ 27 марта 2020

У меня есть функция, позволяющая пользователю редактировать объект json, а затем проверять его в своем коде, поэтому у меня есть 2 json объекта для сравнения и проверки (исходный и отредактированный), я переместить все ключи из объекта json в 2 разных массива, а затем сравнить первый массив со вторым и отфильтровать недостающие ключи.

Код работает для остальной части сценария ios (если я удаляю ключи который имеет объект), но завершается ошибкой, если json имеет ключ, который имеет массив объектов, а также начинает отфильтровывать ключи, которые не были удалены.

Пример: условия, порядок при удалении начинает отображать все ключи в условных выражениях как отфильтрованные

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

note : - для примера стекаблица я написал одну и ту же функцию дважды

let defaultJsonFormFields = [];
let editedJsonFormFields = []

function keyList1(obj){
    Object.keys(obj).forEach(function (key) {
        defaultJsonFormFields.push(key);
        if (typeof (obj[key]) == 'object') {
            keyList1(obj[key]);
        }
    });
};

function keyList2(obj){
    Object.keys(obj).forEach(function (key) {
        editedJsonFormFields.push(key);
        if (typeof (obj[key]) == 'object') {
            keyList2(obj[key]);
        }
    });
};


keyList1(defaultjson);
keyList2(editedjson);

console.log(defaultJsonFormFields);
console.log(editedJsonFormFields);

let result = defaultJsonFormFields.filter(item => editedJsonFormFields.indexOf(item) == -1)

console.log(result)

[stackblitzlink] https://stackblitz.com/edit/js-qkgdoa?file=index.js

let defaultjson =
 {
    "conditionals": [
        {
            "order": "1",
            "key": "gefvsgwer",
            "value": "dghthdffbhrthrdvgrthtuem",
            "grpOperation": "wrfllkwjflmefveveveve",
            "condition": ">"
        }
    ],
    "offset": "15",
    "alert": {
    "mAlertType": "so new thing",
    "mTitle": "abcdef",
    "mMessage": "ok so be it",
    "mNotificationMsg": "whatever",
    "mSeverity": "LOW",
    "mEnabled": "true"
    }
}

let editedjson = {
    "": [
        {
            "": "1",
            "key": "gefvsgwer",
            "value": "dghthdffbhrthrdvgrthtuem",
            "grpOperation": "wrfllkwjflmefveveveve",
            "condition": ">"
         }
    ],
    "": "15",
    "": {
    "": "so new thing",
    "mTitle": "abcdef",
    "mMessage": "ok so be it",
    "mNotificationMsg": "whatever",
    "mSeverity": "LOW",
    "mEnabled": "true"
    }
}

Stackblitz ссылка с фактической функциональностью

https://stackblitz.com/edit/angular-mat-tooltip-x1gtcp?file=app%2Fjson-input.component.ts

При наведении курсора на первый столбец в таблице появляется всплывающая подсказка, при нажатии кнопки открывается диалоговое окно, в котором есть правка json раздел, при нажатии кнопки «Добавить как новое предупреждение» я хочу проверить, какие ключи были удалены из значения по умолчанию json

Ответы [ 2 ]

1 голос
/ 03 апреля 2020

Обновление 2:

Подумав немного, я понял, что RegExp -s может работать в вашем случае без особых хлопот.

Ключи в JSON относительно легко отличить guish от строковых значений:

function test(str, regexp) {
  console.log(
    Array.from(str.matchAll(regexp), m => m[1])
  )
}
// to match a key
test(`{"key1": 1, "key2": 2}`, /\"(.*?)\":/g)
// to match a key followed by spases
test(`{"key1" \n: 1, "key2"\t: 2}`, /\"(.*?)\"\s*:/g)
// to ignore string values
test(`{"key1": "qwer", "key2": 2}`, /\"([^"]*?)\"\s*:/g)
// to ignore escapes in string values
test(`{"key1": "\\"not_a_key\\":", "key2": 2}`, /(?<!\\)\"([^"]*?)(?<!\\)\"\s*:/g)

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

let defaultJsonFormFields = [
  "conditionals", "order", "key", "value", "grpOperation", "condition",
  "offset",
  "alert",
  "mAlertType", "mTitle", "mMessage", "mNotificationMsg", "mSeverity", "mEnabled",
]

const editedjson_str = '{\
  "": [{\
    "": "1",\
    "key": "gefvsgwer",\
    "value": "dghthdffbhrthrdvgrthtuem",\
    "grpOperation": "wrfllkwjflmefveveveve",\
    "condition": ">"\
  }],\
  "": "15",\
  "": {\
    "": "so new thing",\
    "mTitle": "abcdef",\
    "mMessage": "ok so be it",\
    "mNotificationMsg": "whatever",\
    "mSeverity": "LOW",\
    "mEnabled": "true"\
  }\
}'

let editedjson
// before checking the keys, try to  parse editedjson_str
// - no need to report key errors if JSON is invalid in general
//try {
    editedjson = JSON.parse(editedjson_str)
//} catch() { ... }

const editedJsonFormFields = Array.from(editedjson_str.matchAll(/(?<!\\)\"([^"]*?)(?<!\\)\"\s*:/g), m => m[1])
let result = defaultJsonFormFields.filter(item => editedJsonFormFields.indexOf(item) == -1)
console.log(result)

Но все же этот подход выглядит как грязный хак.


Оригинальный ответ:

единственное, что вам нужно, это log ваш editedjson, и вы увидите, что это не то, что вы ожидаете. Попробуйте:

let editedjson = {
    "": [{
            "": "1",
            "key": "gefvsgwer",
            "value": "dghthdffbhrthrdvgrthtuem",
            "grpOperation": "wrfllkwjflmefveveveve",
            "condition": ">"
        }],
    "": "15",
    "": {
        "": "so new thing",
        "mTitle": "abcdef",
        "mMessage": "ok so be it",
        "mNotificationMsg": "whatever",
        "mSeverity": "LOW",
        "mEnabled": "true"
    }
}
console.log(editedjson)

Причина этого в том, что объекты не могут содержать разные значения для одного и того же ключа (и JSON). В этом случае у вас есть root из editedjson 3 клавиш с одинаковым значением "", и остается только последняя. Другие перезаписываются.

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

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

Обновление:

После обновления на ваш вопрос я перешел по вашей второй ссылке к действительному функционалу и понял, что должен был поскорее предложить " код, который будет делать ". Как я вижу, вы действительно получаете от пользователя строку , и, как я сказал , вы действительно не должны . Вы не получите нигде с JSON.parse(). И я не могу дать вам полноценный парсер для , даже не JSON с произвольными ошибками в нем. Все, что я могу предложить в этом случае:

  1. Лучшее решение: использовать формы, с отдельным полем для каждого значения. Как видно из примера, данные имеют постоянную структуру (также вы сравниваете ее с предопределенной defaultjson). Если это так - нет причин усложнять что-либо для пользователя и для себя
  2. Используйте regexp-s, чтобы проверить, отсутствует ли какой-либо ключ из defaultJsonFormFields в строке. Или если есть дубликаты ключей. И только потом попробуйте JSON.parse(). Но у вас будут тяжелые времена с большим количеством крайних случаев. Например, отличая

    { ... "key": "some text" ... }
    

    от

    { ... "wrong key": "key" ... }
    
  3. Для данных произвольной структуры просто измените свой подход к сообщению об ошибках: если нет editedjson.conditionals - сообщите об этом, и не пытайтесь сообщить, что editedjson.conditionals.order также отсутствует, но как-то все нормально с editedjson.conditionals.grpOperation (потому что это не так - нет такого пути, как editedjson.conditionals.grpOperation) *
0 голосов
/ 07 апреля 2020

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

В основном JSON синтаксический анализатор увидит этот отредактированный json с единственным свойством

let editedjson = {
"": [
    {
        "": "1",
        "key": "gefvsgwer",
        "value": "dghthdffbhrthrdvgrthtuem",
        "grpOperation": "wrfllkwjflmefveveveve",
        "condition": ">"
     }
],
"": "15",
"": {
     "": "so new thing",
     "mTitle": "abcdef",
     "mMessage": "ok so be it",
     "mNotificationMsg": "whatever",
     "mSeverity": "LOW",
     "mEnabled": "true"
    }
}

Вывод

let editedjson = {
"": {
      "": "so new thing",
      "mTitle": "abcdef",
      "mMessage": "ok so be it",
      "mNotificationMsg": "whatever",
      "mSeverity": "LOW",
      "mEnabled": "true"
    }
}

И вы не сможете вернуть эти удаленные свойства.

Однако есть способ продолжать терять эти ключи в вашем существующем приложении. Я внес некоторые изменения в это приложение

Я добавил еще одну функцию в событие OnChange текстовой области, которая будет отслеживать изменение этого объекта и добавит «ключ» + i (где я буду инкрементным числом) везде, где пользователь удалил из этого json.

В то время это отредактированное json будет выглядеть так:

let editedjson = {
"key1": [
    {
        "key0": "1",
        "key": "gefvsgwer",
        "value": "dghthdffbhrthrdvgrthtuem",
        "grpOperation": "wrfllkwjflmefveveveve",
        "condition": ">"
     }
],
"key2": "15",
"key4": {
     "key3": "so new thing",
     "mTitle": "abcdef",
     "mMessage": "ok so be it",
     "mNotificationMsg": "whatever",
     "mSeverity": "LOW",
     "mEnabled": "true"
    }
}

Тогда вы можете легко сравнить с вашим предыдущим значением, и оно должно быть точным.

Здесь такое стек * блиц ссылка

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