Filter nested objects by property - javascript

I am consuming a (badly designed) API which sends the following response:
{
"0" : {
"name" : "John",
"last_name" : "Doe"
},
"1" : {
"name": "Mary",
"last_name": "Ann"
},
[...]
}
As you may have noticed, it is a large JSON object with nested objects. Since it isn't an array, i can't use .filter(). So, how can i filter this large object by a nested object property (e.g. name or last_name)?

You can make it as array using Object.values(type).flat(). Then it will make the object values as single array.
const input1 = {
"0" : {
"name" : "John",
"last_name" : "Doe"
},
"1" : {
"name": "Mary",
"last_name": "Ann"
}
}
function search(input, key) {
return Object.values(input).flat().filter(({ name }) => name === key);
}
console.log(search(input1, "John"));

Related

How to resolve error: "undefined" when reading single values from JSON using JavaScript?

I have a JavaScript function that outputs all values from a JSON file to a Terminal, but when attempting to print a single value, I get the following error: Line 74 - Cannot read properties of undefined (reading 'width')
Here is the code:
var json = `{
"columns": [{
"fname": "John",
"lname": "Doe",
"age": "23"
},
{
"fname": "Jane",
"lname": "Doe",
"age": ""
},
{
"fname": "Tom",
"lname": "Johns",
"age": ""
},
{
"fname": "Brian",
"lname": "Wicks",
"age": "27"
},
{
"fname": "Tim",
"lname": "Stone",
"age": ""
},
{
"fname": "Fred",
"lname": "Wilson",
"age": ""
},
{
"fname": "Jason",
"lname": "Voorhees",
"age": "90"
}
],
"rows": [{
"data": {
"width": "2",
"height": "7",
"length": "",
"finalresult": "44",
"firstresult": "",
"secondresult": "300.00",
"thirdresult": "700.40"
}
}]
}`;
var obj = JSON.parse(json);
function printValues(obj) {
for(var k in obj) {
if(obj[k] instanceof Object) {
printValues(obj[k]);
} else {
console.log(obj[k] + "\n");
};
}
};
// Printing all the values from the resulting object
printValues(obj);
//print single value
//console.log(obj["columns"]["rows"]["data"]["width"] + "\n");
console.log("Print Indiviual values:");
console.log(obj["rows"]["data"]["width"] + "\n"); //The Error
...Could I get some assistance as to what I'm doing wrong? ...Thanks
As #Yarin and #codemonkey pointed out—you're trying to access the data object as a direct object property of rows, e.g. obj.rows.data which is wrong and will return undefined because data is not a property of the rows object. Instead it's the first (and only) entry in the array of objects that is rows.
You need to either change the syntax to:
obj.rows[0].data.width
Or take the data object out of the array and remove the array so that the rows object is structured like this:
const obj = {
rows: {
data: {
width: 1
}
}
}
// Then you can use this syntax...
console.log( obj.rows.data.width )
// or even this syntax if you want to...
console.log( obj['rows']['data']['width'] )
I see that the width is the property of object data that is inside array rows...

Create json object dynamic in nodejs

I have json :
{
"fullName": "abc",
"age": 19,
...
}
I want use Nodejs to add element in above json to object named Variables in below json
{
"variables": {
"fullName" : {
"value" : "abc",
"type" : "String"
},
"age": {
"value" : 19,
"type": "Number"
},
...
}
}
Please help me this case!
You can use Object.entries with .reduce()
let data = {
"fullName": "abc",
"age": 19,
}
let result = Object.entries(data).reduce((a, [key, value]) => {
a.variables[key] = { value, type: typeof value}
return a;
}, { variables: {}})
console.log(result);
We can first entries of that object and then map it accordingly after that we convert that object using Object.fromentries. Here is an implementation:
const obj = { "fullName": "abc", "age": 19 };
const result = Object.fromEntries(Object.entries(obj).map(([k,value])=>[k,{value, type:typeof value}]));
console.log({variable:result});
Are you looking for JSON.parse to get a struct from your file, then JSON.stringify to create a json from your struct ?

Merge 2 object arrays in json files by key

I'm trying to combine 2 object array in javascript/jquery matching them by the same key (code). These object arrays are stored in 2 separate json files.
I've cut these down as the files are long
Thanks in advance if anyone can help.
Object 1:
[{
"city": "london",
"selfemployed": {
"job" :"Builder",
"code": "abc"
},
"company" : {
"job": "Shopkeeper",
"code": "def"
}
}]
Object 2:
[{
"code": "abc",
"participant": {
"firstname" : "Joe",
"lastname" : "Blogs"
}
},
{
"code": "def",
"participant": {
"firstname" : "Anna",
"lastname" : "Smith"
}
}]
Needed result:
[{
"city": "london",
"selfemployed": {
"job" :"Builder",
"code": "abc",
"participant": {
"firstname" : "Joe",
"lastname" : "Blogs"
}
},
"company" : {
"job": "Shopkeeper",
"code": "def",
"participant": {
"firstname" : "Anna",
"lastname" : "Smith"
}
}
}]
One of my issues is that I'm unable to return the object from the .json files
var file1 = 'url/file1.json';
var file1 = 'url/file2.json';
const joinJson = (file1, file2) => {
$.getJSON(file, function(data1) {
return data1;
});
$.getJSON(file2, function(data2) {
return data2;
});
// do stuff with data1 and data2
}
console.log(joinJson());
You could take a Map and build new objects for the result by selecting the wanted code information for the new object.
This proposal uses rest properties of an object with babel for older user agents.
var cities = [{ city: "london", selfemployed: { job: "Builder", code: "abc" }, company: { job: "Shopkeeper", code: "def" } }],
codes = [{ code: "abc", participant: { firstname: "Joe", lastname: "Blogs" } }, { code: "def", participant: { firstname: "Anna", lastname: "Smith" } }],
codesMap = new Map(codes.map(({ code, participant }) => [code, participant])),
result = cities.map(
({ city, ...items }) =>
Object.assign({ city }, ...Object.entries(items).map(
([k, v]) => ({ [k]: Object.assign({}, v, codesMap.get(v.code)) })
))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The problem is that you're getting the files asynchronously, and returning data in the callback of that async operation, which goes nowhere. Something like this would be better:
var file1 = 'url/file1.json';
var file1 = 'url/file2.json';
const joinJson = (file1, file2) => {
$.getJSON(file, function(data1) {
// async operation 1 complete. Start operation 2.
$.getJSON(file2, function(data2) {
// async operation 2 complete
// data1 and data2 are now available here
console.log("Data 1:", data1);
console.log("Data 2:", data2);
// This will merge the keys of both objects
// but you can replace it with custom merging logic
var merged = Object.assign(data1, data2);
console.log(merged);
});
});
}
The problem here is that you can't do something like console.log(joinJson());. You may very well need something like a Promise.

conditional operator to check same value in an array then filter it

I have an array with user who has a property with the latitude.
How can i do if i want to create a new array with user who has the same latitude ?
my array looks like this :
let arrayToFilter = [
{
"user1" : {
"profile" : {
"name" : "user1",
"age" : "35",
"gender" : "male",
"latitude" : 57.267801888216965,
"longitude" : 16.451598081831214
}
},
"user2" : {
"profile" : {
"name" : "user2",
"age" : "50",
"gender" : "male",
"latitude" : 37.785834,
"longitude" : -122.406417
}
},
"user3" : {
"profile" : {
"name" : "user3",
"age" : "23",
"latitude" : 37.785834,
"longitude" : -122.406417
}
}
}
]
i´ve tried with this, but this does not seem to work...
let arr = arrayToFilter.filter(child => child.latitude === child.latitude)
the problem is your arrayToFilter, it is an array but it has just one item and inside that object you have a key/value user with the information, thus the steps are the following:
loop over the array.
loop over the keys to get the items
finally loop over the users to get the desired info.
notice that because we are doing a map then another map and then filter we are going to get a similar structure as you gave.
Array -> Array -> UserObject.
let user = {
name: 'test',
latitude: 57.267801888216965
}
let arrayToFilter = [{
"user1": {
"profile": {
"name": "user1",
"age": "35",
"gender": "male",
"latitude": 57.267801888216965,
"longitude": 16.451598081831214
}
},
"user2": {
"profile": {
"name": "user2",
"age": "50",
"gender": "male",
"latitude": 37.785834,
"longitude": -122.406417
}
},
"user3": {
"profile": {
"name": "user3",
"age": "23",
"latitude": 37.785834,
"longitude": -122.406417
}
}
}]
//we have to loop over the array because it is an array of objects and the users are actually inside the object of the first item.
let filtered = arrayToFilter.map(items => {
//here we are going to loop to get the keys and then iti will return us an arrar
//with the items inside, then we can apply the filter.
return Object.keys(items).map(k => items[k]).filter(u => u.profile.latitude === user.latitude)
})
console.log(filtered);
The error with your code is that you are comparing the user to itself. Your filter queries whether the user's latitude is equal to its own latitude, this is true for all users and you will get an array back with all users.
It should instead be:
let arr = arrayToFilter.filter(child => child.latitude === latitudeToCompare)
Where latitudeToCompare is the latitude at which you would like to find users with the same latitude.
If what you are looking for is a "group by" option in Javascript, then as per this Stackoverflow post can be implemented with a slight variation as follows:
var groupBy = function(xs, [min, max]) {
return xs.reduce(function(rv, x) {
(min < rv[x['latitude']] < max || []).push(x);
return rv;
}, {});
};
where xs is the array of user objects, and min/max are the minimum and maximum latitude to create a range or bucket of latitudes.
You should be able to use the above to help you figure out a solution for your problem.

How to better structure an Array of Arrays in JSON

In the following JSON object:
var employees = { "accounting" : [ // accounting is an array in employees.
{ "firstName" : "John", // First element
"lastName" : "Doe",
"age" : 23 },
{ "firstName" : "Mary", // Second Element
"lastName" : "Smith",
"age" : 32 }
], // End "accounting" array.
"sales" : [ // Sales is another array in employees.
{ "firstName" : "Sally", // First Element
"lastName" : "Green",
"age" : 27 },
{ "firstName" : "Jim", // Second Element
"lastName" : "Galley",
"age" : 41 }
] // End "sales" Array.
} // End Employees
How do I restructure the object so I can access each employee first name like this:
employees[0].firstName
employees[1].firstName
// etc
It would require restructuring it so that you'd eliminate the "accounting/sales" properties and make employees an Array of Objects.
Example: http://jsfiddle.net/hgMXw/
var employees = [
{
"dept": "accounting", // new property for this object
"firstName": "John",
// First element
"lastName": "Doe",
"age": 23
},
{
"dept": "accounting", // new property for this object
"firstName": "Mary",
// Second Element
"lastName": "Smith",
"age": 32
},
{
"dept": "sales", // new property for this object
"firstName": "Sally",
// Third Element
"lastName": "Green",
"age": 27
},
{
"dept": "sales", // new property for this object
"firstName": "Jim",
// Fourth Element
"lastName": "Galley",
"age": 41
}
]
You can't pivot this like that. Either you move the department as a key in the employee object or you have to access it like employees.accounting[0].firstName.
If you insist on accessing the employee as employees[index], you have to restructure it to:
var employees = [
{ "firstName" : "John", "lastName" : "Doe", "age" : 23, "department" : "accounting" },
{ "firstName" : "...", ..., "department" : "accounting" },
... and so on.
];
and introduce a different way to filter by department.
maybe create a function that loop through the employees array, and copy each element that match the filter into a new array object and return it.
function getAllEmployeesFilteredBy(filterName, filterValue, empArray)
{
var result = [];
for (var i=0; i < empArray.length; i++) {
if (empArray[i][filterName] === filterValue)
//by ref
result[result.length] = empArray[i];
//or if you prefer by value (different object altogether)
//result[result.length] = { "firstName" : empArray[i].firstName, "lastName" : empArray[i].lastName, ... }
}
return result;
}
From jsFiddle
var employees = { "firstName" : "John", // First element
"lastName" : "Doe",
"age" : 23 },
{ "firstName" : "Mary", // Second Element
"lastName" : "Smith",
"age" : 32 }
;
alert(employees);

Categories

Resources