To Filter Out The Missing Keys After Comparing Two Json Objects(used Js Filter But Doesnt Work For All The Scenarios)
Solution 1:
Update 2:
After a little bit of thinking I realized that RegExp
-s could work in your case without much of a fuss.
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.
Original answer:
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)
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.
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.
Update:
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:
- 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 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 toJSON.parse()
. But you will have hard times with a lot of edge cases. E.g. distinguishing{ ... "key": "some text" ... }
from
{ ... "wrong key": "key" ... }
- 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 thateditedjson.conditionals.order
is also missing, but somehow everything is fine witheditedjson.conditionals.grpOperation
(because it's not - there is no such path aseditedjson.conditionals.grpOperation
as well)
Solution 2:
I am not seeing any way to parse this JSON as it needs unique keys and will remove prior duplicate keys.
Basically JSON parser will see this edited json having single property
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"
}
}
Output
let editedjson = {
"": {
"": "so new thing",
"mTitle": "abcdef",
"mMessage": "ok so be it",
"mNotificationMsg": "whatever",
"mSeverity": "LOW",
"mEnabled": "true"
}
}
And there is no way you can get back these removed properties.
However there is a way to keep loosing these keys in your existing application. I made some changes in that application
I added another function on "OnChange" event of the text area which will track this object change and will add 'key'+ i (where i will be incremental number) wherever user had removed from this json.
At that time this edited json will look like this:
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"
}
}
Then you can easily compare with your prev value and it should be exact.
Here is the stackblitz link
Post a Comment for "To Filter Out The Missing Keys After Comparing Two Json Objects(used Js Filter But Doesnt Work For All The Scenarios)"