Copying/Rename JSON Object Array - javascript

Am getting Data from server in below JSON format
{
"Data": [
{
"Id": "1",
"Number": 0,
"Modify": {
"Id": 0,
"Name": "a"
}
},
{
"Id": "2",
"Number": 1,
"Modify": {
"Id": 1,
"Name": "b"
}
}
]}
And am trying to create a new copy(Rename) of Modify inside the same object because my other data is expecting JSON with same format but different name for modify.
So i though i would foreach and create copy of the same which will form like below
{
"Data": [
{
"Id": "1",
"Number": 0,
"Modify": {
"Id": 0,
"Name": "a"
},"New": {
"Id": 0,
"Name": "a"
}
},
{
"Id": "2",
"Number": 1,
"Modify": {
"Id": 1,
"Name": "b"
},
"New": {
"Id": 1,
"Name": "b"
}
}
]}
Is there a better approach i can rename the object or should i create a copy. What is the better way to copy ?
Thanks

For loop is a fine way to do that.. data[i].Name = data[i].Modify;. Im fairly sure there isn't a "better" way than this in Javascript.

There's no other way than the one suggested by #MjrKusanagi, nevertheless I suggest another approach.
Make a function that takes your original object and replaces the selected key with the new name, returning a new object without changing the original one (immutability)
The function could take 3 arguments:
function modifyObject(object, oldKey, newKey) {...}
Inside the function you could use the Object.assign method to create a copy of the original object (a copy, not a reference):
var newObj = Object.assign({}, object);
After that, you can change the key name by creating a new one and don't forget to remove old key from the new object:
newObj.newKey = newObj.oldKey;
delete newObj.oldKey,
Finally you can return this new object and even use this function every time you need to do anything similar.
Using the delete is considered bad practice, but at least here you are not mutating your original source, so you can depend in its content over all your application's life cycle.

Related

Losing values from redux object when spreading into new object

I'm fetching data from redux store with useSelector.
const customerProduct = useSelector((state) => state.objects.customersProducts[match.params.customerProductId]);
If I log the data it is displayed like this in the console:
Once I try to use spread operator to create a new object, it would lose all the values with (...).
Like this:
const updatedCustomerProduct = { ...customerProduct, newValue: "abc" };
I would get an output like this:
const uptdatedCustomerProduct =
{
"id": "AALzgGxtlg",
"_objCount": 6360,
"newValue": "abc",
"className": "customerOfferMetadata"
}
What's going on here? How could I handle these values? If I copy the object from the console the object is perfectly visible.
Even in redux dev tools the data is displayed like this:
{
"entityInfo": {
"productId": 441,
"bundleOfferId": 22
},
"title": {
"us": "Special Offer"
},
"desc": {
"us": "6 months"
},
"order": 0,
"enabled": true,
"entityType": "product",
"detailsUrl": "www.google.com",
"thumb": {
"__type": "Pointer",
"className": "Resource",
"objectId": "12345"
},
"createdAt": "2021-02-26T18:48:25.358Z",
"updatedAt": "2021-09-21T21:41:49.384Z",
"clientId": 1,
"objectId": "AALzgGxtlg"
}
I'm not sure what code is generating those objects for you, but when you see properties in the console that are semitransparent, they are non-enumerable. This means that when applying the spread operator, they are not iterated over, and hence they do not make it into the new object.
To make all properties enumerable, check out the question Make all properties enumerable.

How can we access the Child Key from Object

I'm trying to loop my child array but it's not working. It's working fine which it's first items but not working on the child elements.
"candidateApplication": [
{
"label": "Are you currently attending school?",
"id": "ap_currentschool",
"value": "",
"required": "N",
"type": "radio",
"display": null,
"list": [
{
"searchCode": "yes",
"searchValue": "yes"
},
{
"searchCode": "no",
"searchValue": "no"
}
],
"onSelect": [
{
"yes": [
{
"label": "Estimated Completion Date",
"id": "ap_compdate",
"value": "",
"required": "N",
"type": "date",
"display": null,
"list": null,
"onSelect": null
}
],
"no": null
}
]
},
]
I am easily access my data to looping lists like obj.candidateApplication.list But I am not able to loop through obj.candidateApplication.onSelect.yes.
Can anybody please guide me how can I fix that issue.
enter image description here
You are accessing obj.candidateApplication.onSelect.yes which is undefined because obj.candidateApplication.onSelect is an array of objects.
You probably want to loop over obj.candidateApplication.onSelect and then for each object you can access the yes property as you wish:
$.each(onSelect, function (index, element) {
$.each(element.yes, function (x, y) {
// your code here
})
});
Edit: As pointed by Heritic Monkey in the comments, obj.candidateApplication is an array as well, but in the picture attached to the question, there's already a local variable called onSelect, loop through that instead of obj.candidateApplication.onSelect because it's undefined. (at least it should be, we don't know what your code is doing)

Looping through multiple arrays in a single JSON file (Vanilla JS)

I am trying to populate my HTML template with data from a JSON file I have created. However, I have two different arrays in that file, each of them containing multiple objects, and I do not know how to loop through them since I need to loop through them in separate functions.
The JS code I have provided below works if I were to have one big array in the JSON file ("product" being the array I am looping through), the problem is that I need to loop through the "glass" and the "wood" arrays separately (in different functions). Ideally, the JS snippet below would loop through the "wood" array.
I have only fetched from one big array before, so I don't really know how to approach this issue. I know this must be something super easy, but I am stuck and would appreciate any hints I can get! Thanks in advance.
JS file:
function init() {
if (window.location.href.includes("wood")) {
fetchJson();
}
}
function fetchJson() {
fetch("products.json")
.then((res) => res.json())
.then(getWoodGallery(product));
}
function getWoodGallery(product) {
product.forEach(showWoodGallery);
}
/*--- display wood products ---*/
function showWoodGallery(product) {
console.log(product);
const woodTemplate = document.querySelector("#woodGalleryTemplate").content;
const woodTemplateCopy = woodTemplate.cloneNode(true);
const woodList = document.querySelector("#woodList");
woodTemplateCopy.querySelector("h2.name").textContent =
"Name: " + `${product.wood}`;
woodTemplateCopy.querySelector("p.dimensions").textContent =
"Dimensions: " + `${product.dimensions}`;
woodTemplateCopy.querySelector("h3.price").textContent =
"Price: " + `${product.price}`;
woodTemplateCopy.querySelector(".btn").textContent = `Buy Now`;
woodList.appendChild(woodTemplateCopy);
}
JSON file:
{
"wood": [
{
"id": "1",
"image": "http://mauriciolondono.be/wp/wp-content/uploads/2020/01/animales_1.jpeg",
"name": "Butterfly",
"dimensions": "30 x 45cm",
"price": 40,
"btn": ""
},
{
"id": "19",
"image": "http://mauriciolondono.be/wp/wp-content/uploads/2020/01/symmetry_4.jpeg",
"name": "Escher deconstructed",
"dimensions": "30 x 45cm",
"price": 20,
"btn": ""
}
],
"glass": [
{
"id": "20",
"image": "http://mauriciolondono.be/wp/wp-content/uploads/2020/01/vidrio_17.jpeg",
"name": "Juntos pero no revueltos",
"dimensions": "30 x 45cm",
"price": 20,
"btn": ""
},
{
"id": "21",
"image": "http://mauriciolondono.be/wp/wp-content/uploads/2020/01/vidrio_11.jpeg",
"name": "White & green",
"dimensions": "30 x 45cm",
"price": 20,
"btn": ""
}
]
}
You just need to loop over the JSON objects keys and conditionally run the function you need to run for that particular key.
function parse(payload) {
Object.keys(payload).forEach((key) => {
switch(key) {
case 'wood':
handleWood(payload[key]);
break;
case 'glass':
handleGlass(payload[key]);
break;
// so on...
}
})
}
Here, Object.keys will give you an array of all the keys of the object. We then iterate over the returned array with forEach running the callback for each iteration. Inside the callback we are just matching the key and running the required function.

How to get an array inside an array?

Hi I have trouble with an array response of json.
I'm supposed to get the members of the objects. but that array is inside another array.
This is the array that is being returned.
var arr = [
[
{
"id": 4243430853,
"email": "jayduco2#gmail.com",
},
{
"id": 4227666181,
"email": "deofederickduran#gmail.com",
},
{
"id": 4227644293,
"email": "kfsucayan#gmail.com",
}
],
[
{
"id": 4243430854,
"email": "jayduco2#gmail.com",
},
{
"id": 4227666182,
"email": "deofederickduran#gmail.com",
},
{
"id": 4227644294,
"email": "kfsucayan#gmail.com",
}
]
];
How can i dig down to the values? before I would use arr[i].email, but now it doesn't work. I've tried arr[0].[i].email, but returns be the error missing name after . operator. Is there a way that I can remove that outer array?
It should be arr[i][j].email. i to loop over the array arr itself and j to loop over each sub-array.
arr[i] will give you something like this (if i == 0 for example):
[
{
"id": 4243430853,
"email": "jayduco2#gmail.com",
},
{
"id": 4227666181,
"email": "deofederickduran#gmail.com",
},
{
"id": 4227644293,
"email": "kfsucayan#gmail.com",
}
]
and then arr[i][j] will give something like this (if i == 0 and j == 2):
{
"id": 4227644293,
"email": "kfsucayan#gmail.com",
}
then you can access the email property using arr[i][j].email.
There's two ways to access objects in Javascript: using periods or using square brackets. Here, you're trying to mix the two, which works, but probably isn't the best practice. You should pick whichever is best for the situation. Here, you'd want to use the brackets:
arr[i][j]["email"];
Note that when using variables, you will always need to use brackets as opposed to periods.

Javascript - searching object by key

I know there's plenty of answers on this and most are suggesting looping thru the object, returning what you need, I'm not sure this is the best approach, in my case anyway.
What I have is array with entries referencing to another array people(with id and name) by person_id and projects(with id and name) by project_id.
What I need is to be able to access project and person with a particular id inside the loop on entries, so I can get their names. Doing what others have suggested I'd loop thru people and projects inside each irritation of entries, which seems like awful lot of looping.
So I thought I'd make something I called a "hashtable" from both people and projects on init, which means pretty much creating a new objects people_hashtable and projects_hashtable where key would be the id
so
[
{
"id": "8",
"name": "John Doe"
}
]
would became
{
"8": {
"name": "John Doe"
}
}
this way I'd have easy access to the name without looping all the time while still maintaining the old array with its original order(that's why I'm not outputting it this way directly from server, you can't quite order an object and I'm using both people and projects in a selectbox, which needs to be ordered by name).
Am I doing it right? Are there better way? Or should I forget this completely and stick with the search loop as suggested in other question?
I'm trying to be as efficient as possible on both server and client side.
You basically doubled all the objects just to avoid loop. So, unless you have some bad performance issues, I would avoid that.
In case you really, really need a kind of hashmap, I would prefer storing the array's index instead of another copy of the object:
// array
var arr = [
{
"id": "8",
"name": "John Doe"
}
];
// lookup table
var lookup = {
"8": 0
}
Of course doing that, means you can't modifying the array's without rebuild the hashmap.
Generate it's quite simple:
var lookup = arr.reduce(function(lookup, item, index) {
lookup[item.id] = index;
return lookup;
}, {});
You can also use that to generate the object you mentioned your question:
var lookup = arr.reduce(function(lookup, item) {
lookup[item.id] = {name: item.name};
return lookup;
}, {});
But as I said it's something I would avoid.
Following code may help you. JSFIDDLE
var arr = [
{
"id": "8",
"name": "John Doe"
}
];
var obj = {};
for(var i=0; i< arr.length; i++){
obj[arr[i].id] = {name: arr[i].name};
}
console.log(obj);
var articles= {
"item1":{
"id":"155",
"name":"First Item",
"value":-5199.6
},
"item2":{
"id":"255",
"name":"Second Item",
"value":-424.91
}
}
var ids = [];
for(var item in articles) {
ids.push(articles[item]['id']);
}
console.log(ids);
This lib https://github.com/paularmstrong/normalizr makes it pretty easy to do. Both normalization and denormalization.
It can turn this
{
"id": "123",
"author": {
"id": "1",
"name": "Paul"
},
"title": "My awesome blog post",
"comments": [
{
"id": "324",
"commenter": {
"id": "2",
"name": "Nicole"
}
}
]
}
into this
{
result: "123",
entities: {
"articles": {
"123": {
id: "123",
author: "1",
title: "My awesome blog post",
comments: [ "324" ]
}
},
"users": {
"1": { "id": "1", "name": "Paul" },
"2": { "id": "2", "name": "Nicole" }
},
"comments": {
"324": { id: "324", "commenter": "2" }
}
}
}
and the other way around.

Categories