Iterate through array of objects using javascript - javascript

I am trying to iterate through the array of objects but somehow not getting it right. Can somone please let me know where i am going wrong.
Here is the data
const response = {
"pass": 1,
"fail": 2,
"projects_all": [
{
"projects": [
{
"name": "Project1",
"current": null,
"previous": {
"environment": "qa4nc",
"status": "UNKNOWN",
}
}
]
},
{
"projects": [
{
"name": "Project2",
"current": null,
"previous": {
"environment": "qa4nc",
"status": "FAIL",
}
},
{
"name": "Project3",
"status": "LIVE",
"current": null,
"previous": {
"environment": "qa4nc",
"status": "UNKNOWN",
}
}
]
}
]
}
And here is the code i tried
if(response) {
response?.projects_all?.forEach((projects) => {
projects.forEach(project) => {
if(project.previous !== null) {
//do something here
}
});
});
}
I am trying to iterate through this array of objects but it says projects not iterable. Any help is appreciated to make me understand where i am going wrong.

You were missing iterating over an array properly. A good idea is to format the JSON object that you plan to iterate over. So that you can see what are the arrays and objects, and at what hierarchy.
if (response) {
response?.projects_all?.forEach((project) => {
project?.projects?.forEach((project) => {
console.log(project?.name);
});
}
);
}

response?.projects_all?.forEach((projects) => {
This is the exact correct way to start the code. The problem that happens next is you apparently misunderstand what projects means in the following context
You do projects.forEach(project) as if you think projects is as array. projects is not an array at this point, it is an object that looks like this:
{
"projects": [
{
"name": "Project1",
"current": null,
"previous": {
"environment": "qa4nc",
"status": "UNKNOWN",
}
}
]
}
So I would actually want to do projects.projects.forEach(project => { ... }), or you could change the variable name from projects so it makes more sense to read.

First, determine what shape your response object currently has.
By using the ?. operator your essentially muting JS built in error reporting.
From the context, I assume your response actually looks like this:
console.log(response);
{
data: {
projects_all: [ ... ]
}
}
Therefore your existing code using response?.projects_all doesn't actually hit the projects_all property inside your response.
Can you try the following:
response.data.projects_all.forEach((project) => {
console.info("Project: ", project);
project.projects.forEach((project) => {
console.log(project, project?.name);
});
});
Alternatively, if you don't have a data key inside your response object, you can omit it in the loop:
response.data.projects_all.forEach((project) => {
console.info("Project: ", project);
project.projects.forEach((project) => {
console.log(project, project?.name);
});
});

Related

How can I loop over a multi level JSON object and create a new Javascript object from one of it's key and values

I have a JSON object that looks like the following
{
"venue": {
"time1": [
{
"Status": "Available"
},
{
"Status": "Unavailable"
},
{
"Status": "Unavailable"
}
],
"time2": [
{
"Status": "Available"
},
{
"Status": "Available"
},
{
"Status": "Unavailable"
}
]
}
}
I want to loop over this object and create a new object that has the times as the key and an array of status' as it's values. So the new object would look like the following...
{
"time1": ["Available", "Unavailable", "Unavailable"],
"time2": ["Available", "Available", "Unavailable"]
}
NB: I'm struggling with this, because i can't manage to reach the array. I have tried various maps, reduce etc. but with no joy, and I can't seem to find the right answer on SO because, I'm not sure what to search for.
Run a reduce over object's key-value pairs to get the desired result.
Here is a snippet for your reference. Comments are inline
const obj = {
venue: {
time1: [{Status: "Available"},{Status: "Unavailable" },{Status: "Unavailable" }],
time2: [{Status: "Available" },{Status: "Available" },{Status: "Unavailable" }]
}
};
const result = Object.entries(obj.venue).reduce((acc, element) => {
// Destrcuture key, values here
const [key, status] = element;
// Run a map to fetch the status and then assign it to the key
acc[key] = status.map((item) => item.Status);
return acc;
}, {});
console.log(result);
The JavaScript Object obj.venue is converted into an array (Object.entries(obj.venue)), each of their timeX arrays is then processed (get the Status-value of each object) and eventually it is converted back into an object again using Object.fromEntries().
All this can be done in a single line of code:
const obj= {venue: {time1: [{Status: "Available"},{Status: "Unavailable"},{Status: "Unavailable"}],
time2: [{Status: "Available"},{Status: "Available"},{Status: "Unavailable"}]} };
const res=Object.fromEntries(Object.entries(obj.venue).map(([k,v])=>[k,v.map(st=>st.Status)]));
console.log(obj); // original object remains unchanged
console.log(res);
const a = Object.values(your_object)[0];
a['time1'] = a['time1'].flatMap(x=>Object.values(x))
a['time2'] = a['time2'].flatMap(x=>Object.values(x))
console.log(a)
/*
{
time1: [ 'Available', 'Unavailable', 'Unavailable' ],
time2: [ 'Available', 'Available', 'Unavailable' ]
}
*/
POJO (Plain old javascript object) cannot be iterated: Iterable Objects
The only solution is to read the object entries and then access the internal array. However, note that iterating over object does not guarantee that the order is maintained SO discussion
That said, you can use any of the object iterable methods ["keys", "values", "entries"] to access the inner data.
Using entries()
Object.entries(jsonObj.venue).map(entry => console.log(entry))
hope this code helping you
var json= {
"venue": {
"time1": [
{
"Status": "Available"
},
{
"Status": "Unavailable"
},
{
"Status": "Unavailable"
}
],
"time2": [
{
"Status": "Available"
},
{
"Status": "Available"
},
{
"Status": "Unavailable"
}
]
}
}
Object.keys(json.venue).map((obj,index)=>json.venue[obj] = json.venue[obj].flatMap(ele=>Object.values(ele)),[])
console.log(json)

Make CreateQueryBuilder return nested object instead of one flat object

I'm using Typescript with TypeORM. Using CreateQueryBuilder, I want to receive a nested object. Instead I'm receiving a single flat object as represented in block number two. How can I fix this?
const x = await getConnection()
.createQueryBuilder()
.select(['reportHead', 'order', 'workOrder'])
.from('report_head', 'reportHead')
.innerJoin('reportHead.workOrder', 'workOrder')
.innerJoin('workOrder.order', 'order')
.where(`order.customer.id = :customerId`, { customerId: req.user.customer.id })
.execute();
How can I avoid the data looking like this:
{
"reportHead_id": "asd",
"reportHead_number": "123",
"workOrder_id": "dsa",
"workOrder_status: "OK",
"order_id": "sda",
"order_whatev": "ks"
}
but rather have a neste object like this:
{
"reportHead": {
"id": ...
},
"workOrder": {
"id": ...
},
"order": {
"id": ...
}
}
The solution was to not use .execute(), but rather .getMany().

Construct a JSON Payload in javascript

I have to construct a JSON payload that looks like this, can someone help me? I am able to get the straight forward one but unable to build a nested payload. How do I go about adding more nested keys, one inside the other. Also some of the keys and values are dynamic and have to replaced with variables.
{
"format_version": "0.2.19",
"alliances": {
"xyz": {
"environments": {
"prd": {
"teams": {
"abc": {
"action": "edit",
"team": "abc",
"projects": {
"prjabc": {
"project": "prjabc",
"cost_center": "0",
"custom_iam_policies": [],
"iam": {
"view_group_email_name": "abc#email.com",
"sre_admin_group_email_name": "xyz#email.com"
},
"allowed_apis": [
"api1",
"api2"
],
"networks": {
"network1": {
"flags": [
"VM"
],
"region": "sample-region",
"preferred-suffix": "routable"
}
}
}
}
}
}
}
}
}
}
}
Let say you have an object as such
items = {
foo: "bar",
something: "useful"
}
and if you wanted to add other properties or add nested object you can do so like this
subitems = { name: "Johnson" };
items['subitem'] = subitems;
After you've added and finalized the object, you can just use JSON.stringify(items) to convert your object into "payload"

Wildcard Search in a collection with lodash

I've an array like the one shown below and I want to do a wildcard search and retrieve the corresponding value. This is not returning me any result, can someone help me if there is any better way to do this. I'm using lodash utilities in my nodejs application.
var allmCar = [
{
"_id": ObjectId("5833527e25bf78ac0f4ca30e"),
"type": "mCar",
"value": "ABDC",
"__v": 0
},
{
"_id": ObjectId("5833527e25bf78ac0f4ca30e"),
"type": "mCar",
"value": "XYZ ABD",
"__v": 0
},
{
"_id": ObjectId("5833527e25bf78ac0f4ca30e"),
"type": "mCar",
"value": "FGHJ",
"__v": 0
}
]
_.find(allmCar, {
value: {
$regex: 'XYZ'
}
})
I finally ended up using _.includes as below
_.each(allmCar,function(car){
if(_.includes('XYZ', car.value)===true)
return car;
})
You can do the same with a function passed to _.find, like this
_.find(allmCar, function(mCar) {
return /XYZ/.test(mCar.value);
});
Or with arrow functions,
_.find(allmCar, (mCar) => /XYZ/.test(mCar.value));
This will apply the function passed to all the items of the collection and if an item returns true, that item will be returned.

Angular - Convert Jackson output to JSON

The server I'm working with changed the REST format from plain JSON:
{
"removedVertices": [
{
"id": "1",
"info": {
"host": "myhost",
"port": "1111"
},
"name": "Roy",
"type": "Worker"
}
],
"id": "2",
"time": 1481183401573
}
To Jackson format:
{
"removedVertices": [
"java.util.ArrayList",
[
{
"id": "1",
"info": [
"java.util.HashMap",
{
"host": "myhost",
"port": "1111"
}
]
"name": "Roy",
"type": "Worker",
}
]
"id": "2",
"time": 1482392323858
}
How can I parse it the way it was before in Angular/Javascript?
Assuming only arrays are affected, I would use underscore.js and write a recursive function to remove the Jackson type.
function jackson2json(input) {
return _.mapObject(input, function(val, key) {
if (_.isArray(val) && val.length > 1) {
// discard the Jackson type and keep the 2nd element of the array
return val[1];
}
else if (_.isObject(val)) {
// apply the transformation recursively
return jackson2json(val);
}
else {
// keep the value unchanged (i.e. primitive types)
return val;
}
});
}
If the api should be restful, then the server should not return none plain json results. I think the server site need to fix that.
I think it is because the server enabled the Polymorphic Type Handling feature.
Read Jackson Default Typing for object containing a field of Map and JacksonPolymorphicDeserialization.
Disable the feature and you will get result identical to plain json.
The main difference i see is that in arrays you have an additional string element at index 0.
If you always get the same structure you can do like this:
function jacksonToJson(jackson) {
jackson.removedVertices.splice(0, 1);
jackson.removedVertices.forEach((rmVert) => {
rmVert.info.splice(0, 1);
});
return jackson;
}

Categories

Resources