在比较两个json对象之后过滤掉丢失的键(使用js过滤器,但不适用于所有情况) [英] To filter out the missing keys after comparing two json objects(used js filter but doesnt work for all the scenarios)

查看:72
本文介绍了在比较两个json对象之后过滤掉丢失的键(使用js过滤器,但不适用于所有情况)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个功能,可以使用户编辑json对象,然后在我的代码中对其进行验证,因此我有2个json对象要进行比较和验证(初始和已编辑的json对象),我按了所有键从json对象分为2个不同的数组,然后将第一个数组与第二个数组进行比较,并过滤掉丢失的键.

I have a functionality where I enable the user to edit the json object and then validate it in my code, so I have 2 json objects to compare and validate(the initial and the edited one) , I am pushing all the keys from json object into 2 different arrays and then comparing the first array to second and filtering out the missing keys.

该代码适用于其余场景(如果我删除了具有对象的键),但是如果json的键具有包含对象数组的键,并且也开始过滤出尚未删除的键,则该代码将失败.

The code works for rest of the scenarios(if I remove keys which has an object) but fails if the json has a key which has an array of objects and also starts filtering out the keys which has not been removed.

Ex:条件语句,删除后的顺序开始显示条件条件下的所有键都被过滤掉

但是,如果我删除处于警报或偏移状态的按键,则会显示正确的编号和已过滤出的按键名称.

But if I remove keys under alert or offset it shows correct number and name of keys filtered out.

注意:-对于stackblitz示例,我已经编写了两次相同的函数

note:- for the stackblitz example I have written same function twice

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链接

Stackblitz link with actual functionality

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

将鼠标悬停在表的第一列上时,将显示一个工具提示,单击按钮对话框打开,该对话框具有edit json部分,单击另存为新警报"时,我要检查已从列表中删除了哪些键.默认json

On hovering over the first column in table , a tooltip appears , on click of the button dialog box opens up which has edit json section, on click of Add As New Alert I want to check what all keys have been removed from the default json

推荐答案

更新2:

经过一番思考,我意识到RegExp -s可以在您的情况下正常工作,而不必大惊小怪.

After a little bit of thinking I realized that RegExp-s could work in your case without much of a fuss.

JSON 中的键相对容易与字符串值区分开:

Keys in JSON are relatively easy to distinguish from string values:

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)

所以回到您的代码...您可以在以下代码段中看到正确的结果:

So back to your code... You can see correct result in the following snippet:

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)

但是这种方法仍然感觉很脏.

But still this approach feels like a dirty hack.

原始答案:

您唯一需要做的就是log您的editedjson,您会发现这不是您所期望的.试试吧:

The only thing you need is to log your editedjson and you will see that it is not what you expect. Try it:

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)包含不同的值.在这种情况下,您在editedjson的根中具有3个具有相同值""的键,只有最后一个保留.其他人被覆盖.

The reason for this is that objects can't contain different value for the same key (and JSON as well). In this case you have in the root of editedjson 3 keys with the same value "", and only the last one stays. Others are overwritten.

如果您要弄清您要实现的确切行为,我可以用将要执行的代码更新答案.

If you'll clarify what is the exact behavior are you trying to achieve, I can update my answer with the code that will do.

主要问题是,您无法从用户那里获得具有唯一键的对象.但是您可以得到一个字符串(它可能不应该被称为 JSON )...但是您实际上不是必须的,因为您必须通过以下方式对其进行解析:你自己.因此,您需要为用户期望的数据选择其他格式.

The main issue is that you just can't get from a user an object with keys that are not unique. But you can get a string (and it probably shouldn't be called JSON)... but you really mustn't, because you'll have to parse it by yourself. So you need to choose another format for the data you expect from a user.

更新:

在更新您的问题之后,我遵循了您的确实从用户那里收到了一个字符串,而且正如我所说的您确实不能. JSON.parse()将无济于事.而且,我无法为您提供完整的解析器,而不是甚至没有JSON 的解析器,其中都包含任意错误.在这种情况下,我只能建议:

After update to your question I followed your second link to the actual functionality and realized that I was to quick to suggest "the code that will do". As I see, you do receive a string from a user, and as I said you really mustn't. You will get nowhere with JSON.parse(). And I can not give you a full fledged parser for a not even a JSON with arbitrary errors in it. All I can suggest in this case is:

  1. 最佳解决方案:使用表格,为每个值使用单独的字段. 正如我在示例中看到的那样,数据具有恒定的结构(也可以将其与预定义的defaultjson进行比较).如果是这样-没有理由让用户和您自己变得复杂
  2. 使用regexp -s检查字符串中是否缺少defaultJsonFormFields中的任何键.或者,如果有重复的密钥.然后只有尝试JSON.parse().但是您会遇到很多困难的情况.例如.区别

  1. The best solution: use forms, with separate field for each value. As I see in the example, the data have a constant structure (also you compare it to the predefined defaultjson). If that's so - there is no reason to complicate things for a user and for yourself
  2. Use regexp-s to check if any key from the defaultJsonFormFields are missing in the string. Or if there are duplicate keys. And only then try to JSON.parse(). But you will have hard times with a lot of edge cases. E.g. distinguishing

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

来自

{ ... "wrong key": "key" ... }

  • 对于任意结构的数据,只需更改错误报告的方法即可:如果没有editedjson.conditionals-报告它,并且不要尝试报告editedjson.conditionals.order也丢失了,但是使用editedjson.conditionals.grpOperation(因为不是-也没有editedjson.conditionals.grpOperation这样的路径)
  • For data of arbitrary structure, just change you approach for error reporting: if there is no editedjson.conditionals - report it, and don't try to report that editedjson.conditionals.order is also missing, but somehow everything is fine with editedjson.conditionals.grpOperation (because it's not - there is no such path as editedjson.conditionals.grpOperation as well)
  • 这篇关于在比较两个json对象之后过滤掉丢失的键(使用js过滤器,但不适用于所有情况)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆