Changing the value of JSON object's key, changes other values also
The problem was with the creation of JSON,
jsonCreator()
. LinejsonObj.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
How to Refresh Form Page After Post Request
Localstorage Values Get Reset After Refreshing Page and Inserting New Values
Angular 2 Concatenate Variable in Interpolation
How to Output a Pdf Buffer to Browser Using Nodejs
Check If Image Exists on Server Using JavaScript
How to Set Image to Fit Width of the Page Using Jspdf
How to Disable Clicking Inside Div
Securityerror: Blocked a Frame With Origin from Accessing a Cross-Origin Frame
How Exactly Use and Update the Global Variables in React-Native
Blocking Device Rotation on Mobile Web Pages
Regex in JavaScript Allow Only Numbers and One Dot Followed by Max 2 Number
How to Apply the Length Condition on the Existing Regular Expression
How to Close Toggle Menu When Clicking Navigation Item Anchor Link
Changing the Value of Json Object's Key, Changes Other Values Also
Restrict to 2 Decimal Places in Keypress of a Text Box
Opening Pdf String in New Window With JavaScript