Changing the Value of Json Object's Key, Changes Other Values Also

Changing the value of JSON object's key, changes other values also

The problem was with the creation of JSON, jsonCreator(). Line jsonObj.AF = af_Array; was not copying, it was just assigning a reference.

Solution found, with the suggestion of @ccarton, converted JSON_OBJECT to string and parse back.

var currentUserID = '123';
var formulaType = 'FORMULA-1'

var JSON_OBJECT1 = JSON.stringify(JSON_OBJECT);
JSON_OBJECT = JSON.parse(JSON_OBJECT1)

Object.keys(JSON_OBJECT).forEach(function(k) {
if (currentUserID == JSON_OBJECT[k]['user_id']) {
JSON_OBJECT[k]['AF'][0]['formula_type'] = formulaType;
}
});

Javascript: I am updating the value of an object key. BUT after the update another key pair also changes value

Addressing the immediate problem: each line has a lineClassification prop, which is itself an object. As lines are being iterated, some of those lineClassification's are being placed in another array (summaryClassification). Subsequent turns of the outer loop are looking up elements of the array and mutating them, but these lineClassifications are the same objects pointed to by the lines.

Here's a much more minimal MRE to illustrate...

const lines = [
{ name: 'line0', classificationObject: { name: 'class0', number: 10 } },
{ name: 'line1', classificationObject: { name: 'class1', number: 10 } },
{ name: 'line2', classificationObject: { name: 'class0', number: 10 } },
]

let summary = []

for (line of lines) {
let classificationObject = line.classificationObject;
let classificationName = classificationObject.name
let index = summary.findIndex(s => s.name === classificationName);
if (index == -1) {
summary.push(classificationObject); // the problem is here.
// the SAME classification object now appears in TWO places:
// in the line object, and in the summary array
// future mutations will be seen by both
} else {
// as a result, this line seems to modify two objects
// it's really modifying one object, pointed to from multiple places
summary[index].number += 12
}
}

console.log("logging the summary, it's what we expect. The saved class0 classification has been mutated:")
console.log(summary)

console.log("But logging the lines, we're surprised to find line 0's classification object has been mutated. it happens because that same object was also placed in the summary array, and was mutated in a subequent turn of the loop:")
console.log(lines)

Change value in json object based on other key value

You had a few problems in your code, mainly you were confusing Path and path (JavaScript is case sensitive) and you were missing the var keyword in the for (this one is subtle and very dangerous), but you weren't that far from the goal.

Here's a fixed function :

var obj = [{
"name": "abc",
"Path": "i.abc",
"count": 5347,
"subFolders": []
},
{
"name": "cde",
"Path": "i.cde",
"count": 0,
"subFolders": [{
"name": "efg",
"Path": "",
"count": 0,
"subFolders": []
},
{
"name": "hij",
"Path": "i.hij",
"count": 1,
"subFolders": []
}]
}];

function upd(o, path, count) {
if (o.Path == path) {
o.count = count;
} else {
var arr;
if (Array.isArray(o)) arr = o;
else if (o.subFolders) arr = o.subFolders;
else return;
for(var j=0; j < arr.length; j++) {
upd(arr[j], path, count);
}
}
}
upd(obj, "i.hij", 3);
console.log(obj);

I also changed the variable names to remove all references to JSON, as there's no JSON here.

how to change value of all nodes of json array

You can use map to map your objects to new objects. Those objects have a single property, which you can get with Object.keys. The new object can get that same property name using the computed property name feature:

var obj = {    "Urls": [        { "getCar": "/getAllCars" },        { "getPerson": "/getAllPersons" },        { "getBook": "/getAllBooks" }    ],    "ServerUrl": "http://192.168.1.1:3000"};
var urls = obj.Urls.map(o => Object.keys(o).map(k => ({ [k]: obj.ServerUrl + o[k] }))[0]);
console.log(urls);

How to change "key" and "value" keys of to_entries to "ParameterKey" and "ParameterValue" in jq?

Create a new object and assign the fields correspondigly

… | .[] |= {ParameterKey: .key, ParameterValue: .value}

Demo

Instead of the update operator |= you could also use map

… | map({ParameterKey: .key, ParameterValue: .value})

Demo

Depending on the actual structure of your three input files, this can probably be simplified using reduce instead.

Also, if you want to import the actual replacement names from outside jq (as their sample names suggest), use the --arg parameter to create an externally initialized variable and use it when creating the objects

jq -s --arg key "ParameterKey" --arg value "ParameterValue" '
… {($key):.key, ($value):.value} …
'

JQ: How To Change A Value in JSON with embedded keys

SecretString is a field name in an object. Therefore you have to address it using a dot before its name: .SecretString

Also, the content of that field seems to be JSON but encoded as a string which you cannot address directly. You have to decode it first using fromjson and encode it again using tojson. However, the JSON string in your sample data has an error rendering it invalid JSON (after the value \"60\", there is an abundant quotation mark followed by a comma: \",). Assuming this is just a copy/paste error, let's continue:

To update a value using the value itself to begin with, use the update operator |=. To just assign a value use the simple assignment operator =.

Lastly, you can give jq the file to process as a parameter. You don't have to cat it first and then pipe it into jq.

Altogether, this is what you are looking for:

jq '.SecretString |= (fromjson | .ConnectionString = "MyNewConnectionString" | tojson)' json.txt
{
"ARN": "MyArn",
"Name": "MySecret",
"SecretString": "{\"ConnectionString\":\"MyNewConnectionString\",\"SqlCommandTimeout\":\"60\",\"ServiceAccountPrincipal\":\"MyServicePrincipal\"}",
"VersionStages": [
"AWSCURRENT"
],
"CreatedDate": "2022-01-13T09:08:55.442000-08:00"
}

Demo

Some additional notes:

If you want to keep the inner JSON as JSON (to access it more easily in th future), just drop the re-conversion with tojson)

To manipulate more than just one value, simply add them after the first: .ConnectionString = "…" | .SqlCommandTimeout = "…" | .ServiceAccountPrincipal = "…"

You can also provide the new value(s) as parameter(s) and access them as variable(s) instead, which makes your filter a little less cluttered, especially if you intend to change more than just that one field.

jq --arg v "MyNewConnectionString" '… .ConnectionString = $v …' json.txt


Related Topics



Leave a reply



Submit