Updating a JSON object using Javascript - javascript

How can i update the following JSON object dynamically using javascript or Jquery?
var jsonObj = [{'Id':'1','Username':'Ray','FatherName':'Thompson'},
{'Id':'2','Username':'Steve','FatherName':'Johnson'},
{'Id':'3','Username':'Albert','FatherName':'Einstein'}]
I would like to dynamically update the Username to 'Thomas' where the 'Id' is '3'.
How can I achieve this?

A plain JavaScript solution, assuming jsonObj already contains JSON:
Loop over it looking for the matching Id, set the corresponding Username, and break from the loop after the matched item has been modified:
for (var i = 0; i < jsonObj.length; i++) {
if (jsonObj[i].Id === 3) {
jsonObj[i].Username = "Thomas";
break;
}
}
Here it is on jsFiddle.
Here's the same thing wrapped in a function:
function setUsername(id, newUsername) {
for (var i = 0; i < jsonObj.length; i++) {
if (jsonObj[i].Id === id) {
jsonObj[i].Username = newUsername;
return;
}
}
}
// Call as
setUsername(3, "Thomas");

simply iterate over the list then check the properties of each object.
for (var i = 0; i < jsonObj.length; ++i) {
if (jsonObj[i]['Id'] === '3') {
jsonObj[i]['Username'] = 'Thomas';
}
}

$(document).ready(function(){
var jsonObj = [{'Id':'1','Username':'Ray','FatherName':'Thompson'},
{'Id':'2','Username':'Steve','FatherName':'Johnson'},
{'Id':'3','Username':'Albert','FatherName':'Einstein'}];
$.each(jsonObj,function(i,v){
if (v.Id == 3) {
v.Username = "Thomas";
return false;
}
});
alert("New Username: " + jsonObj[2].Username);
});

use:
var parsedobj = jQuery.parseJSON( jsonObj);
This will only be useful if you don't need the format to stay in string.
otherwise you'd have to convert this back to JSON using the JSON library.

var i = jsonObj.length;
while ( i --> 0 ) {
if ( jsonObj[i].Id === 3 ) {
jsonObj[ i ].Username = 'Thomas';
break;
}
}
Or, if the array is always ordered by the IDs:
jsonObj[ 2 ].Username = 'Thomas';

JSON is the JavaScript Object Notation. There is no such thing as a JSON object. JSON is just a way of representing a JavaScript object in text.
So what you're after is a way of updating a in in-memory JavaScript object. qiao's answer shows how to do that simply enough.

I took Michael Berkowski's answer a step (or two) farther and created a more flexible function allowing any lookup field and any target field. For fun I threw splat (*) capability in there incase someone might want to do a replace all. jQuery is NOT needed. checkAllRows allows the option to break from the search on found for performance or the previously mentioned replace all.
function setVal(update) {
/* Included to show an option if you care to use jQuery
var defaults = { jsonRS: null, lookupField: null, lookupKey: null,
targetField: null, targetData: null, checkAllRows: false };
//update = $.extend({}, defaults, update); */
for (var i = 0; i < update.jsonRS.length; i++) {
if (update.jsonRS[i][update.lookupField] === update.lookupKey || update.lookupKey === '*') {
update.jsonRS[i][update.targetField] = update.targetData;
if (!update.checkAllRows) { return; }
}
}
}
var jsonObj = [{'Id':'1','Username':'Ray','FatherName':'Thompson'},
{'Id':'2','Username':'Steve','FatherName':'Johnson'},
{'Id':'3','Username':'Albert','FatherName':'Einstein'}]
With your data you would use like:
var update = {
jsonRS: jsonObj,
lookupField: "Id",
lookupKey: 2,
targetField: "Username",
targetData: "Thomas",
checkAllRows: false
};
setVal(update);
And Bob's your Uncle. :) [Works great]

For example I am using this technique in Basket functionality.
Let us add new Item to Basket.
var productArray=[];
$(document).on('click','[cartBtn]',function(e){
e.preventDefault();
$(this).html('<i class="fa fa-check"></i>Added to cart');
console.log('Item added ');
var productJSON={"id":$(this).attr('pr_id'), "nameEn":$(this).attr('pr_name_en'), "price":$(this).attr('pr_price'), "image":$(this).attr('pr_image'), "quantity":1, "discount":0, "total":$(this).attr('pr_price')};
if(localStorage.getObj('product')!==null){
productArray=localStorage.getObj('product');
productArray.push(productJSON);
localStorage.setObj('product', productArray);
}
else{
productArray.push(productJSON);
localStorage.setObj('product', productArray);
}
itemCountInCart(productArray.length);
});
After adding some item to basket - generates json array like this
[
{
"id": "95",
"nameEn": "New Braslet",
"price": "8776",
"image": "1462012394815.jpeg",
"quantity": 1,
"discount": 0,
"total": "8776"
},
{
"id": "96",
"nameEn": "new braslet",
"price": "76",
"image": "1462012431497.jpeg",
"quantity": 1,
"discount": 0,
"total": "76"
},
{
"id": "97",
"nameEn": "khjk",
"price": "87",
"image": "1462012483421.jpeg",
"quantity": 1,
"discount": 0,
"total": "87"
}
]
For Removing some item from Basket.
$(document).on('click','[itemRemoveBtn]',function(){
var arrayFromLocal=localStorage.getObj('product');
findAndRemove(arrayFromLocal,"id",$(this).attr('basketproductid'));
localStorage.setObj('product', arrayFromLocal);
loadBasketFromLocalStorageAndRender();
});
//This function will remove element by specified property. In my case this is ID.
function findAndRemove(array, property, value) {
array.forEach(function(result, index) {
if(result[property] === value) {
//Remove from array
console.log('Removed from index is '+index+' result is '+JSON.stringify(result));
array.splice(index, 1);
}
});
}
And Finally the real answer of the question "Updating a JSON object using JS". In my example updating product quantity and total price on changing the "number" element value.
$(document).on('keyup mouseup','input[type=number]',function(){
var arrayFromLocal=localStorage.getObj('product');
setQuantityAndTotalPrice(arrayFromLocal,$(this).attr('updateItemid'),$(this).val());
localStorage.setObj('product', arrayFromLocal);
loadBasketFromLocalStorageAndRender();
});
function setQuantityAndTotalPrice(array,id,quantity) {
array.forEach(function(result, index) {
if(result.id === id) {
result.quantity=quantity;
result.total=(quantity*result.price);
}
});
}

I think this the more efficent way than for looping.
1-First find index of item.
2-Second edit exact element. (if not exist add)
Example :
let index= jsonObj.findIndex(x => x["Id"] === 3);
if (index == -1) {
// add
jsonObj.push({ id:3, .... });
} else {
// update
jsonObj[index]["Username"]="xoxo_gossip_girl"
}

var jsonObj = [{'Id':'1','Quantity':'2','Done':'0','state':'todo',
'product_id':[315,"[LBI-W-SL-3-AG-TA004-C650-36] LAURA BONELLI-WOMEN'S-SANDAL"],
'Username':'Ray','FatherName':'Thompson'},
{'Id':'2','Quantity':'2','Done':'0','state':'todo',
'product_id':[314,"[LBI-W-SL-3-AG-TA004-C650-36] LAURA BONELLI-WOMEN'S-SANDAL"],
'Username':'Steve','FatherName':'Johnson'},
{'Id':'3','Quantity':'2','Done':'0','state':'todo',
'product_id':[316,"[LBI-W-SL-3-AG-TA004-C650-36] LAURA BONELLI-WOMEN'S-SANDAL"],
'Username':'Albert','FatherName':'Einstein'}];
for (var i = 0; i < jsonObj.length; ++i) {
if (jsonObj[i]['product_id'][0] === 314) {
this.onemorecartonsamenumber();
jsonObj[i]['Done'] = ""+this.quantity_done+"";
if(jsonObj[i]['Quantity'] === jsonObj[i]['Done']){
console.log('both are equal');
jsonObj[i]['state'] = 'packed';
}else{
console.log('not equal');
jsonObj[i]['state'] = 'todo';
}
console.log('quantiy',jsonObj[i]['Quantity']);
console.log('done',jsonObj[i]['Done']);
}
}
console.log('final',jsonObj);
}
quantity_done: any = 0;
onemorecartonsamenumber() {
this.quantity_done += 1;
console.log(this.quantity_done + 1);
}

//update & push json value into json object
var sales1 = [];
if (jsonObj && Object.keys(jsonObj ).length != 0) {
jsonObj .map((value) => {
const check = sales1.filter(x => x.order_date === String(value.order_date).substring(0, 10))
if (check.length) {
sales1.filter(x => x.sale_price = Number(x.sale_price) + Number(value.sale_price))
} else {
let data = { "sale_price": Number(value.sale_price), "order_date": String(value.order_date).substring(0, 10) }
sales1.push(data)
}
})
}

You can easily update the username dynamically to 'Thomas' where the 'Id' is '3' using the following.
jsonObj.find(i=>i.Id===3).Username='Thomas'

Related

Find in object to Edit or Add

I have an object productCounts
[{provisioned=2.0, product=str1, totalID=1.0},
{product=str2, provisioned=4.0, totalID=3.0},
{provisioned=6.0, product=str3, totalID=5.0}]
I have an array uniqueProduct
[str1, str2, str3, str4]
I am then looping a dataset to get the totalID count, add it to the product's totalID but if it doesn't exist, push it to the object.
var countID = 0;
uniqueProduct.forEach(
currentproduct => {
countID = 0;
for (var i = 0; i < shtRng.length; ++i) {
if (shtRng[i][ProductCol].toString() == currentproduct) { // && shtRng[i][IDcol].toString().length>4){
countID++;
}
}
if (countID == 0) {
return;
}
console.log(currentproduct + ": " + countID);
}
)
This works perfectly to return the countID per product in uniqueProduct
Rather than logging the result, I would like to add it to the object like this... If the current unique product is not in the productCounts object, add it.
let obj = productCounts.find((o, i) => {
if (o.product == currentproduct) {
productCounts[i] = { product: currentproduct, totalID: productCounts[i].totalID+countID, provisioned: productCounts[i].provisioned };
return true;
} else {
productCounts.push({ product: currentproduct, totalID: countID, provisioned: 0 });
return true;
}
});
In my head, this should work but it appears to skip some records or add the product multiple times. How do I add to the object correctly?
Expected output is the object to be something similar to:
[{provisioned=2.0, product=str1, totalID=35.0},
{product=str2, provisioned=4.0, totalID=8.0},
{provisioned=6.0, product=str3, totalID=51.0},
{provisioned=6.0, product=str4, totalID=14.0}]
The argument to find() is a function that returns a boolean when the element matches the criteria. The if statement should use the result of this, it shouldn't be in the condition function.
let obj = productCounts.find(o => o.product == currentProduct);
if (obj) {
obj.totalId += countID;
} else {
productCounts.push(productCounts.push({ product: currentproduct, totalID: countID, provisioned: 0 });
}
BTW, your life would be easier if you used an object whose keys are the product names, rather than an array of objects. You can easily turn the array of objects into such an object:
let productCountsObj = Object.fromEntries(productCounts.map(o => [o.product, o]));
if (currentProduct in productCountsObj) {
productCountsObj[currentProduct].totalID += countID;
} else {
productCountsObj[currentProduct] = { product: currentproduct, totalID: countID, provisioned: 0 };
}

JS: TypeError: Cannot find function keys in object

I have the following in apps script:
function getQAs() {
return [
{ "Do you have any pictures ?|1 ": {"yes":2,"no":3 } },
{ "Do you have any pictures ?|2 ": {"yes":2,"no":3 } },
{ "Do you have any pictures?|3 ": {"yes":2,"no":3 } },
]
}
I'm trying to build a function that will search through the keys of The objects for a number. I'm testing with the number 1 .When I run:
function testQA() {
var qa = getQAs();
var matches = qa.keys().filter(function(row) { //ONLY CHECKED ROWS.
Logger.log(row)
return row.indexOf('1') == true;
});
Logger.log(matches);
}
I get
JS: TypeError: Cannot find function keys in object . What am I doing wrong?
You need to use a for...in loop to get the keys of an object. I devised a simple loop through keys to determine if the value existed within the key, then pushed out a filtered array
function testQA() {
var qa = getQAs();
function getRow(row_identifier) {
var filtered = [];
qa.forEach(function(v) {
for(var k in v) {
if(k.indexOf(row_identifier) > 0) filtered.push(v);
}
});
return filtered;
}
return getRow(row_identifier);
}
function getQAs() {
return [
{
"Do you have any pictures ?|1 ": {
"yes": 2,
"no": 3
}
},
{
"Do you have any pictures ?|2 ": {
"yes": 2,
"no": 3
}
},
{
"Do you have any pictures?|3 ": {
"yes": 2,
"no": 3
}
},
]
}
function testQA() {
var qa = getQAs();
function getRow(row_identifier) {
var filtered = [];
qa.forEach(function(v) {
for(var k in v) {
if(k.indexOf(row_identifier) > 0) filtered.push(v);
}
});
return filtered;
}
console.log(getRow(1));
console.log(getRow(2))
console.log(getRow(3))
}
testQA();
Just playing around with your question
I'm not that good with objects so I thought it would be fun to play around with this and see what I can learn. I have no expectation of having my answer chosen, I just thought it might be valuable to a less experienced programmer, like myself.
function getQAs() {
var qa=[{"Do you have any picture?|1":{yes:"2",no:"3"}},{"Do you have any picture?|2":{yes:"4",no:"5"}},{"Do you have any picture?|3":{yes:"8",no:"9"}}];
return qa;
}
function testQA(row) {
var row=row || 3;
var qa = getQAs();
Logger.log(qa);
var qA=[];
for(var i=0;i<qa.length;i++) {
qA.push(Object.keys(qa[i]));
}
Logger.log(qA);
for(var i=0;i<qA.length;i++) {
if(qA[i].toString().indexOf(row)>-1){
var rv=JSON.stringify(qa[i]);
var t1=qA[i];
var t2=qa[i];
var yeses=t2[t1].yes;
var nos=t2[t1].no;
var t3={yes:yeses,no:nos};
return t3;
break;
}
}
}
Hopefully, someone can learn something from this by single stepping through the program. It returns an object with the number of yeses and noes for the selected object.

How can I get some value of a deep-nested object?

There are two types of arrays which I have to build dynamically.
data['fields']['title']
and
data['fields']['description']['html']
it returns the content of this structure:
{
"fields": {
"title": "Headline",
"description": {
"html": "<p>description text</p>"
}
},
"meta": {
"id": "995915463198380032"
}
}
The problem is "dynamically".
I call a function and give the path through it like "description>html".
I split the string into "description" and "html".
But how do I build now the array: data['fields']['description']['html']
Sometimes there is a level more or less like "title".
If I want to call title, the array is like data['fields']['title']
So the content and the number of parts in the array are dynamic.
I tried by myself this:
function comfort_x(item_fields) {
var splitter = item_fields.split(">");
var content = new Array();
for (var i = 1; i < splitter.length; ++i) {
content['splitter['+i+']'] = splitter[i];
}
data['fields'][splitter[0]][splitter[1]];
}
Thank you for your help.
You can create a function that will look up to the level you are passing. You can just split your path by > and reduce that array with the source input.
(data, path) => path.split(">").reduce((r, e) => r[e], data);
Here is a example.
var obj = {
"fields": {
"title": "Headline",
"description": {
"html": "<p>description text</p>"
}
},
"meta": {
"id": "995915463198380032"
}
}
var lookUp = (o, path) => path.split(">").reduce((r, e) => r[e], o);
console.log('fields: ', lookUp(obj, 'fields'))
console.log('fields>title: ', lookUp(obj, 'fields>title'))
console.log('fields>description>html: ', lookUp(obj, 'fields>description>html'))
It works with this addinitional work-around:
switch (splitter.length) {
case 0:
item.innerHTML = data['fields'];
break;
case 1:
item.innerHTML = data['fields'][splitter[0]];
break;
case 2:
item.innerHTML = data['fields'][splitter[0]][splitter[1]];
break;
case 3:
item.innerHTML = data['fields'][splitter[0]][splitter[1]][splitter[2]];
}
maybe you have a smarter solution.
/*
Be careful! The function won’t return a new object,
but take a reference to the input object aka. alter
it and don’t deep-clone it.
*/
const myObject = {};
function setValueByKeypath(object, path, value, separator = ">") {
path = path.split(separator);
let currentPart = object;
for (let i = 0, len = path.length; i < len; i++) {
const key = path[i];
const keyValue = (i === len - 1) ? value : {};
if (typeof currentPart[key] === "undefined") {
currentPart[key] = keyValue;
}
currentPart = currentPart[key];
}
}
setValueByKeypath(myObject, "fields>description>html", "<p>description text</p>");
console.log(myObject);
setValueByKeypath(myObject, "fields>title", "Headline");
console.log(myObject);
setValueByKeypath(myObject, "meta>id", "995915463198380032");
console.log(myObject);

Correct way to create json from neo4j rest API

I want to create the following json
"model":[
{
"_id": 123,
"innerMode1": [
{
"_id": 233,
"_type": "somtype2",
"innerMode2": [
{
"_id": 24533,
"_type": "somtype3",
"innerMode2": [
{ ....this goes on till depth of 6
}
]
}
]
}
], "_id": 45123,
"innerMode2": [
{
"_id": 23433,
"_type": "somtype2",
"innerMode2": [
{
"_id": 241233,
"_type": "somtype3",
"innerMode2": [
{
....this goes on till depth of 6
}
]
}
]
}
]
.
.
.
.
.
1000 records
cypher something like:
MATCH (c:Capability{SectorID:{varSectorID}})-[r1:CapabilityAdopts_Capability]->(d)-[r2:Capability_Capability]->(e)-[r3:Capability_Capability]->(f)
OPTIONAL MATCH (f)<-[r3:Capability_Capability]-(g)
OPTIONAL MATCH (f)-[r4:KPI_Capability]-(h)
RETURN c,labels(c),r1,Type(r1),d,labels(d),r2,Type(r2),e,labels(e),r3,Type(r3),f,labels(f),r4,Type(r4),g,labels(g),r5,Type(r5),h,labels(h)
CapabilityAdopts_Capability = innerModel1,
Capability_Capability = innerModel2 (direction of arrows are differnt hence data is different)
Capability_Capability = innerMode13 (direction of arrows are differnt hence data is different)
Capability_Capability = innerMode14 (direction of arrows are differnt hence data is different)
var capObjectsContainer= {
model: []
};
var mainContainerL2 = jsonData.results[4].data; //this comes from neo after running the above cypher
for (i = 0; i < mainContainerL2.length; i++) {
var isPartOfCapabilityContainer = {
isPartOfCapability: []
};
var capIsMeasuredByKPIPatternContainer = {
cpbltyIsMsrdByKpiPttrn: []
};
var consistsOfCapContainer = {
consistsOfCapability: []
};
var isconsistsOfCap2Present = false;
for (j = 0; j < capObjectsContainer.model.length; j++) {
if (mainContainerL2[i].row[0]["ExternalID"] == capObjectsContainer.model[j]["_id"]) {
for (k = 0; k < capObjectsContainer.model[j].adoptsCapability.length; k++) {
if (mainContainerL2[i].row[4]["ExternalID"] == capObjectsContainer.model[j].adoptsCapability[k]["_id"]) {
for (l = 0; l < capObjectsContainer.model[j].adoptsCapability[k].consistsOfCapability.length; l++) {
if (mainContainerL2[i].row[8]["ExternalID"] == capObjectsContainer.model[j].adoptsCapability[k].consistsOfCapability[l]["_id"]) {
for (m = 0; m < capObjectsContainer.model[j].adoptsCapability[k].consistsOfCapability[l].consistsOfCapability.length; m++) {
if (mainContainerL2[i].row[12]["ExternalID"] == capObjectsContainer.model[j].adoptsCapability[k].consistsOfCapability[l].consistsOfCapability[m]["_id"]) {
if (mainContainerL2[i].row[20] != null)
AddcapIsMeasuredByKPIPattern(capObjectsContainer.model[j].adoptsCapability[k].consistsOfCapability[l].consistsOfCapability[m].cpbltyIsMsrdByKpiPttrn, mainContainerL2[i].row[20], mainContainerL2[i].row[21])
if (mainContainerL2[i].row[16] != null && !IsExternalIdPresent(capObjectsContainer.model[j].adoptsCapability[k].consistsOfCapability[l].consistsOfCapability[m].isPartOfCapability, mainContainerL2[i].row[16]))
AddIsPartOfCap(capObjectsContainer.model[j].adoptsCapability[k].consistsOfCapability[l].consistsOfCapability[m].isPartOfCapability, mainContainerL2[i].row[16], mainContainerL2[i].row[17])
isconsistsOfCap2Present = true;
break;
}
}
if (!isconsistsOfCap2Present) {
if (mainContainerL2[i].row[20] != null)
AddcapIsMeasuredByKPIPattern(capIsMeasuredByKPIPatternContainer.cpbltyIsMsrdByKpiPttrn, mainContainerL2[i].row[20], mainContainerL2[i].row[21])
if (mainContainerL2[i].row[16] != null)
AddIsPartOfCap(isPartOfCapabilityContainer.isPartOfCapability, mainContainerL2[i].row[16], mainContainerL2[i].row[17])
if (mainContainerL2[i].row[12] != null)
AddConsistsOfCap(capObjectsContainer.model[j].adoptsCapability[k].consistsOfCapability[l].consistsOfCapability, mainContainerL2[i].row[12], mainContainerL2[i].row[13], isPartOfCapabilityContainer.isPartOfCapability, capIsMeasuredByKPIPatternContainer.cpbltyIsMsrdByKpiPttrn, consistsOfCapContainer.consistsOfCapability)
}
break;
}
}
}
}
}
}
}
requirement is there cannot be a round trip to neo. I can hit neo only once and get data. I dont like the above code which i wrote (though it creates json exactly as I want). is there a better cypher query
that I can use to accomplish what I want? I want to get rid of all the loops.
Any functions that I can use or property that can help me here?
Here is a link.
You can use collect + map and collection syntax to create something like you describe in a single cypher statement, you'd start at the lowest level and then work your way upwards aggregating along your paths.
Unfortunately I was not able to follow your explanation.
Here is a link to a article that explains it in detail:
http://gist.neo4j.org/?9269173

Saving nested json object path to a variable via recursion

Is there a way to save the "path" of a json object to a variable? That is, if I have something like this:
var obj = {"Mattress": {
"productDelivered": "Arranged by Retailer",
"productAge": {
"year": "0",
"month": "6"
}
}
};
How can I loop through and save each key node name to a variable? eg. (I need it in this format): Mattress[productDelivered], Mattress[productAge][year], Mattress[productAge][month]
I have got partly there in this fiddle http://jsfiddle.net/4cEwf/ but as you can see in the log, year and month don't get separated but append to the array as well. I know this is because of the looping I have going on but I'm stuck on how to progress to get the data format I require. The flow I have set up in the fiddle is emulating what I need.
Is there a way I haven't considered to do this?
Try
var obj = {
"Mattress": {
"productDelivered": "Arranged by Retailer",
"productAge": {
"year": "0",
"month": "6"
}
}
};
var array = [];
function process(obj, array, current){
var ikey, value;
for(key in obj){
if(obj.hasOwnProperty(key)){
value = obj[key];
ikey = current ? current + '[' + key + ']' : key;
if(typeof value == 'object'){
process(value, array, ikey)
} else {
array.push(ikey)
}
}
}
}
process(obj, array, '');
console.log(array)
Demo: Fiddle
var obj = {"Mattress": {
"productDelivered": "Arranged by Retailer",
"productAge": {
"year": "0",
"month": "6"
}
}
};
var Mattress = new Array();
for(var i in obj.Mattress){
if(typeof(obj.Mattress[i])==='object'){
for(var j in obj.Mattress[i]){
if(Mattress[i]!=undefined){
Mattress[i][j] = obj.Mattress[i][j];
}
else{
Mattress[i] = new Array();
Mattress[i][j] = obj.Mattress[i][j];
}
}
}
else{
Mattress[i] = obj.Mattress[i];
}
}
for(var i in Mattress){
if(typeof(Mattress[i])==='object'){
for(var j in Mattress[i]){
alert(j+":"+Mattress[i][j]);
}
}
else{
alert(i+":"+Mattress[i]);
}
}

Categories