how to format json in angular - javascript

I want to know how to format my json to have key and value using typescript with Angular framework,
with the current method if I use the keyvalue pipe in my html it will work but I want to format the json.
In my example below I have my Current json and the expected json so that you can see the result I expect and to be as clear as possible being a beginner in the business I wanted to be clear
Current.json
{
"url": "url test"
"flight": [
[
"1",
"apollo",
"ariane"
],
[
"2",
"Space X",
"Boca chica"
]
]
}
expected.json // this json is what I would like to have
{
"url": "url test"
"flight": [
[
id: "1",
name: "apollo",
rocket:"ariane"
],
[
id: "2",
name: "Space X",
rocket: "falcon 9"
]
]
}
ts.file
get() {
this.service.get().subscribe((data: Interface[])=> {
this.array = data
});

Your expected Json isn’t valid, if you want property names for those array values you need to make them an object.
{
"url": "url test"
"flight": [
{
id: "1",
name: "apollo",
rocket:"ariane"
},
{
id: "2",
name: "Space X",
rocket: "falcon 9"
}
]
}
To get this format from the example you gave you can do this:
get() {
this.service.get().subscribe((data: Interface[])=> {
data.flight = data.flight.map(f => ({id: f[0], name: f[1], rocket: f[2]}))
this.array = data
});

Please try this code snippet
get() {
this.service.get().subscribe((data: any)=> {
data.flight = data.flight.map(f => {
return {id: f[0], name: f[1], rocket: f[2]}
})
this.array = data
});

Related

How can I find any item inside a array with objects inside [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 months ago.
Improve this question
I have this data
{playstation: Array(1), freefire: Array(1), pubg: Array(1), roblox: Array(1), steam: Array(1), …}
This is what the arrays look like:
freefire: [{…}]
playstation: [{…}]
pubg: [{…}]
razorgold: [{…}]
roblox: [{…}]
steam: [{…}]
{
"freefire": {
"id": 1,
"attributes": {
"ProductCode": "427",
"createdAt": "2022-06-09T11:29:04.187Z",
"updatedAt": "2022-06-09T11:29:05.518Z",
"publishedAt": "2022-06-09T11:29:05.513Z",
"ProductCodeAlt": "FLASH-427",
"Name": "20",
"FaceValue": 20,
"DefaultCost": 2000,
"Description": "R20 Uber Token",
"Vendor": "Uber",
"VendorId": 15,
}
}
}
I am trying to find anything in that data using this method.
const item = data.freefire.find(
(item) => String(item.ProductCode) === ProductCode
);
It does work only by specifying the item path. I do not want to specify it. I just want to do it like this.
const item = data.find(
(item) => String(item.ProductCode) === ProductCode
);
but is seems not to work
Well, take a look to the following code
const data = {
first: [
{
ProductCode: 1,
otherStuff: "other stuff A"
},
{
ProductCode: 1,
otherStuff: "other stuff B"
},
{
ProductCode: 2,
otherStuff: "other stuff X1"
},
],
second: [
{
ProductCode: 1,
otherStuff: "other stuff C"
},
{
ProductCode: 3,
otherStuff: "other stuff X2"
},
{
ProductCode: 2,
otherStuff: "other stuff X3"
},
]
}
const ProductCode = 1;
const result = Object.keys(data).map(key => data[key].filter(item => item.ProductCode === ProductCode)).flat(1);
console.log(result);
This will log
[
{
"ProductCode": 1,
"otherStuff": "other stuff A"
},
{
"ProductCode": 1,
"otherStuff": "other stuff B"
},
{
"ProductCode": 1,
"otherStuff": "other stuff C"
}
]
Edit
An edit have been made to the answer by changing the structure of the objects, the principle is still the same here.
If you're looking for a single search hit, you can look into each key of the main object, go into its array and search, and finally return your find.
const codeToFind = 3;
const data = {
playstation: [{ productCode: 1 }],
freefire: [{ productCode: 2 }],
pubg: [{ productCode: 3 }],
roblox: [{ productCode: 4 }],
steam: [{ productCode: 5 }],
};
let found;
const result = Object.keys(data).find((key) => data[key].find((subObject) => subObject.productCode === codeToFind));

how to limit the number of function each?

I have the following object:
"data": [
{
"label": "dataName",
"sections": [
{
"label": "label sections 1",
"fields": [
{
"id": 1,
"name": "field 1",
"value": "value field 1"
},
{
"id": 2,
"name": "field 2",
"value": "value field 2"
}
]
},
{
"label": "label sections 2",
"fields": [
{
"id": 5,
"name": "field 3",
"value": "value field 3"
}
]
}
]
I would like to create a new array by retrieving data from each field.
like this :
array [
{id: field.id, name: field.name, value: field.value }
{id: field.id, name: field.name, value: field.value }
]
I thought I would use each function like this :
_.each(data, function (elt) {
_.each(elt.ections, function (elt) {
....
})
});
but using the each function I should multiply the functions each.
Is there a solution to get the same result without using several functions each?
If you have a solution ?
Cordially
Use the reduce method:
var reduceSections = data.reduce((a,b) => (a.concat(b.sections)),[]);
var reduceFields = reduceSections.reduce((a,b) => (a.concat(b.fields)),[]);
var result = reduceFields;
console.log(result);
For more information, see
MDN JavaScript Reference - Array.prototype.reduce
MDN JavaScript Reference - Array.prototype.concat
The DEMO
var data = [{
"label": "dataName",
"sections": [{
"label": "label sections 1",
"fields": [{
"id": 1,
"name": "field 1",
"value": "value field 1"
},{
"id": 2,
"name": "field 2",
"value": "value field 2"
}]
},{
"label": "label sections 2",
"fields": [{
"id": 5,
"name": "field 3",
"value": "value field 3"
}]
}]
}];
var reduceSections = data.reduce((a,b) => (a.concat(b.sections)),[]);
var reduceFields = reduceSections.reduce((a,b) => (a.concat(b.fields)),[]);
var result = reduceFields;
console.log(result);
Only downside is that mutating the original data object will mutate the result in the array. (no shallow cloning)
That may or may not be a downside depending on the application.
If you want to clone the objects:
var clone = result.map(obj => Object.assign({},obj));
For more information, see
MDN JavaScript Reference - Object.assign
MDN JavaScript Reference - Array.prototype.map
As you are making use of lodash already, you have access to _.flatMap, _.map and _.clone.
Unfortunately, with your data structure, iterating over the arrays in your data is required, but with depending on what you are trying to achieve, there are alternatives to _.each.
Assuming you want to join all of cloned entries in fields, that are nested in each entry of the array sections, that are nested in each entry of the array data, you can use the following code:
function cloneFields(elt) { return _.map(elt.fields, _.clone) }
var allClonedFields = _.flatMap(data, elt => {
return _.flatMap(elt.sections, cloneFields);
});
The function cloneFields() is initialized outside of the loop for performance so that it isn't created on every iteration.
This code will pull out each entry in data, then from that entry pull out each entry in the sections key, then return the clone of each entry in the fields key and then join them into one large array giving the following result:
[ { id: 1, name: 'field 1', value: 'value field 1' },
{ id: 2, name: 'field 2', value: 'value field 2' },
{ id: 5, name: 'field 3', value: 'value field 3' } ]
If you don't know exactly how "deep" is your object i recommand you using recursive function. Here is what i suggest :
function recursivlyCreateObject(data) {
let result;
if(Array.isArray(data)) {
result = [];
data.forEach(function(element) {
result.push(recursivlyCreateObject(element));
});
} else {
result = {};
Object.keys(data).forEach(function(key) {
result[key] = data[key];
});
}
return result;
}
You can test it here
EDIT : note that this won't do much more than a simple console.log over the data but can help you about iterating an object recursivly
If i understand correctly, you're trying to get the fields property from each element in the array. To do this, take a look at array.map().
using array.map, you could do something like this:
let array = data.map(x => x.fields);
or:
let array = data.map(x => (
{id: x.fields.id,name: x.fields.name, value: x.fields.value }
));
https://www.w3schools.com/jsref/jsref_map.asp

How can I combine this data into one Object?

This one is a tricky one.
So, lets say I have two JS objects that are fetched via REST call, via two callbacks.
So, we have:
call1() - POST method - parsed JSON to JS object, route: {{url}}/data
call1.json:
"data": [
{
"id": "1",
"volume:" "2000"
},
{
"id": "2",
"volume:" "3000"
},
{
"id": "3",
"volume:" "4000"
},
{
"id": "4",
"volume:" "5000"
}
];
call2(req.body.id) - GET method - parsed JSON to JS object, route: {{url}}/data/:id
For example, if I pass req.body.id as = 1 got from the first response, it will open data for that id. So:
return call2(2) will return the data from this JSON: call2.json:
"data": [
{
"id": "1",
"add_data": "important string",
"add_data_2": "important string two"
},
];
The bottom line is, when doing the {{url}}/data route call - call() I need to serve all the data from {{url}}/data/:id routes, and bind them to the correct id. So, for example, the scenario I am trying to achieve is this:
Inside call(): get call1.json: data, do as many call2(req.body.id) calls as there are ids in the first object and then combine add_data and add_data_two values in the first object. So for example the final object would look like this.
console.log(response)
"data": [
{
"id": "1",
"volume:" "2000",
"add_data": "important string",
"add_data_2": "important string two"
},
{
"id": "2",
"volume:" "3000",
"add_data": "important string",
"add_data_2": "important string two"
},
{
"id": "3",
"volume:" "4000",
"add_data": "important string",
"add_data_2": "important string two"
},
{
"id": "4",
"volume:" "5000",
"add_data": "important string",
"add_data_2": "important string two"
}
];
This is what I have tried so far:
async get_data(req) {
try {
const objFirst = await call1(); //gets data
let objTwo = '';
for (let i = 0; i < objFirst.data.length; i++) {
objTwo = await call2({id: objFirst.data[i].id}) //gets data
}
return objFirst;
} catch(err) {
console.log("Error: ", err)
}
}
But it does not work. How can I get all data, and make as many as call2(id) as there are ids and combine that all in one object? Basically, I need to repeat this callback -> call2(id) as many ids we receive in call1().
Thanks, sorry if it looks like a mess.
You can use the map function and spread operator for this. Something like below.
Call2 function just simulates what an endpoint would return, but you get the idea.
var data = [
{
id: 1,
add_data: "1111"
},
{
id: 2,
add_data: "2222"
}
];
var data2 = [
{
id: 1,
volume: "bla"
},
{
id: 2,
volume: "bla"
}
];
function call2(id) {
return data2.filter(x => x.id == id)[0];
}
var result = data.map(x => {
var response = call2(x.id);
return {
...x,
...response
}
})
console.dir(result[0]);
The speed of your solution (loop through an array and doing http calls to get more data is really slow). If you have a lot of these functions that needs to combine data from different datasources, and depending on your project size, i would look into either RXJS or GraphQL (If you really need performance). RXJS have great functions to merge, combine, map etc data.
RXJS
GraphQL

Filter objects based on a match in another array

I am trying to use Lodash to filter an array of objects based on a match of id's, this is what I have tried:
var team = _.find(this.teams, { 'id': this.newSchedule.team});
_.filter(this.yards, function(yard) {
return _.find(team.yards, { id: yard.id });
});
yards data:
[ { "id": 1, "name": "Test" },{ "id": 2, "name": "Test 2" } ]
team data:
[ { "id": 1, "name": "Team 1", "yards": [{ "id": 1, "name" }] ]
I want this.yards to show the yards based on the yard id from a selected team.
Its hard to understand what you mean, does the yard id match the team id?
If so it sounds like what you need to do is first find the team with the same id then grab that teams yards. Therefore I would use the map function twice:
const result = this
.yards
.map(y => team.find(t => t.id === y.id)) // join with the right team
.map(t => t.yards) // reduce to that teams yards
As team is an array, you need to iterate it before doing the _.find on an individual element in that array. It doesn't help that you called your variable team (singular). teams would make more sense.
Here is how you would change your lodash code:
var yards = [ { id: 1, name: "Test" },{ id: 2, name: "Test 2" } ],
teams = [ { id: 1, name: "Team 1", yards: [{ id: 1, name: "Missing string" }] } ]
result = _.filter(this.yards, function(yard) {
return _.some(this.teams, function(team) {
return _.find(team.yards, { id: yard.id });
});
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
So this returns the yards that are related to at least one team.

Angular bind to filtered count

I have this array:
[
{
type: "hhh",
items: [
{
"name": "EGFR",
"type": "a",
"selected": true
}
]
},
{
type: "aaa",
items: [
{
"name": "mm",
"type": "b",
"selected": false
}
]
},
{
type: "ii",
items: [
{
"name": "pp",
"type": "bb",
"selected": true
}
]
}
]
I want to show a counter of the items with selected property "true".
I want it to be changed real time when change.
(Without watch and function)
Thnaks!
Here is the way:
var current_selected = {
get amount(){
var res = 0;
arr.forEach(function(item, i, arr) {
if (item.items[0].selected) res++;
})
return res;
}
}
Calling:
current_selected.amount
Fiddle
You can use JsonPath to get the count. Also using JsonPath has an added advantage of working on complex json structure. For the example you gave, you just need to include jsonpath js file and use the following in your script:
console.log(arr);
var filtered = jsonPath(arr, "$.[*].items[?(#.selected==true)]");
console.log(filtered);
console.log(filtered.length);
where arr is your json structure.
JsonPath can be got from :
https://code.google.com/archive/p/jsonpath/downloads
JsonPath help:
http://goessner.net/articles/JsonPath/
There might be updated version in other sources but that was the one I had worked on

Categories