Create nested JSON array - javascript

I'm trying to create a JSON array to send it to my web service. This is how my json should look like:
[{
"tipus": 1,
"proveidor": 3,
"atributs": {
"atribut":{
"id": 1,
"valor": 8
},
"atribut":{
"id": 2,
"valor": 500
}
}
}]
So, I have two general values "tipus" and "proveidor" and multiple "atributs" each "atribut" is composed with "id" and "valor".
When I construct the json I get this instead of what I want:
[
2:{
"tipus": 1,
"proveidor": 3,
1:{
"id": 1,
"valor": 8
},
0:{
"id": 2,
"valor": 500
}
}]
This is how I'm building the json:
// For every founded in $scope.atrb i need to create an 'atribut' element into my json
$scope.a = [];
var key;
for(key in $scope.atrb){
var newField = {
"idatributs_actiu": $scope.atrb[key].idatributs_actiu,
"nomAtribut": $scope.atrb[key].nomAtribut,
"valor": $scope.atrb[key].valor,
"idActiu": $routeParams.idTipusActiu,
"value": "",
"ordre": $scope.atrb[key].ordre,
"idatributs_generics": $scope.atrb[key].idatributs_generics
};
$scope.a.push(newField);
}
$scope.f = $scope.a;
});
var generics = {
"nom": $scope.nom,
"tipus": $routeParams.idTipusActiu,
"proveidor": $scope.proveidor.id
};
$scope.a.push(generics);
It's my first project with angular and I'm not sure if I'm building the json appropriately, basically i use an array to build a json but I don't know how to nested it 'atribut' inside 'atributs'.
The main idea is to read the 'generics' atributes and then loop through 'atributs' and read all 'atribut' element getting the properties.
Regards

Like S4beR and Kevin B told me, I just need to do an JS array. This is in my controller:
var obj = { generics: g, atributs: $scope.a };
g: it's an object with the generic properties
$scope.a: this is an array with 'atribut' objects which contais all
the properties I need save to.

Related

Javascript - Comparing two arrays then pushing to new array on condition met

Is there any way to compare two arrays and push to an empty array if the condition is met?
Say I have an array of objects. I need to loop through the array of objects, get a ID; then compare that ID to a different array. Then if they match push a value in that array to an empty array?
Array 1:
[{
"addon_service": {
"id": "f6f28cb5-78ad-4ec7-896d-16462b8202fd",
"name": "papertrail"
},
"app": {
"id": "199a1f26-b8e2-43f6-9bab-6e7a6c685ec2",
"name": "mdda-mobiledocdelivery-stg"
}
}]
Array 2
[{
"app": {
"id": "199a1f26-b8e2-43f6-9bab-6e7a6c685ec2"
},
"stage": "staging",
}]
I need to match Array 1 app.ID to Array 2 app.id. If they match check what stage the app is in (staging, development or production). Then push Array 1 addon_service.name to either a staging develpment or
production array depending on what stage the application is in. I'm thinking its simple just cant get my head around it.
I think this is a poorly worded question.
You could use a hash table for lookup and for the stage and use an object for collecting the matches.
var array1 = [{ "addon_service": { "id": "f6f28cb5-78ad-4ec7-896d-16462b8202fd", "name": "papertrail" }, "app": { "id": "199a1f26-b8e2-43f6-9bab-6e7a6c685ec2", "name": "mdda-mobiledocdelivery-stg" } }],
array2 = [{ "app": { "id": "199a1f26-b8e2-43f6-9bab-6e7a6c685ec2" }, "stage": "staging", }],
hash = Object.create(null),
result = {};
array2.forEach(function (a) {
hash[a.app.id] = a.stage;
});
array1.forEach(function (a) {
if (hash[a.app.id]) {
result[hash[a.app.id]] = result[hash[a.app.id]] || [];
result[hash[a.app.id]].push(a.addon_service.name);
}
})
console.log(result);
I think this will do it.
$.each(app1, function(key, value){
$.each(app2, function(k, v){
if(value.app.id == v.app.id){// find apps with the same `id`
if(v[v.stage]){// check if the `stage` array already exists.
v[v.stage].push(value.addon_service)
}else{
v[v.stage] = [value.addon_service];
}
}
});
});
Where app1 is the first array in your question and app2 the second one.

Merge Arrays Combining Matching Objects in Angular Javascript

I have 2 array objects in Angular JS that I wish to merge (overlap/combine) the matching ones.
For example, the Array 1 is like this:
[
{"id":1,"name":"Adam"},
{"id":2,"name":"Smith"},
{"id":3,"name":"Eve"},
{"id":4,"name":"Gary"},
]
Array 2 is like this:
[
{"id":1,"name":"Adam", "checked":true},
{"id":3,"name":"Eve", "checked":true},
]
I want the resulting array after merging to become this:
[
{"id":1,"name":"Adam", "checked":true},
{"id":2,"name":"Smith"},
{"id":3,"name":"Eve", "checked":true},
{"id":4,"name":"Gary"},
]
Is that possible? I have tried angular's array_merge and array_extend like this:
angular.merge([], $scope.array1, $scope.array2);
angular.extend([], $scope.array1, $scope.array2);
But the above method overlap the first 2 objects in array and doesn't merge them based on matching data. Is having a foreach loop the only solution for this?
Can someone guide me here please?
Not sure if this find of merge is supported by AngularJS. I've made a snippet which does exactly the same:
function merge(array1, array2) {
var ids = [];
var merge_obj = [];
array1.map(function(ele) {
if (!(ids.indexOf(ele.id) > -1)) {
ids.push(ele.id);
merge_obj.push(ele);
}
});
array2.map(function(ele) {
var index = ids.indexOf(ele.id);
if (!( index > -1)) {
ids.push(ele.id);
merge_obj.push(ele);
}else{
merge_obj[index] = ele;
}
});
console.log(merge_obj);
}
var array1 = [{
"id": 1,
"name": "Adam"
}, {
"id": 2,
"name": "Smith"
}, {
"id": 3,
"name": "Eve"
}, {
"id": 4,
"name": "Gary"
}, ]
var array2 = [{
"id": 1,
"name": "Adam",
"checked": true
}, {
"id": 3,
"name": "Eve",
"checked": true
}, ];
merge(array1, array2);
Genuinely, extend in Angular works with object instead of array. But we can do small trick in your case. Here is another solution.
// a1, a2 is your arrays
// This is to convert array to object with key is id and value is the array item itself
var a1_ = a1.reduce(function(obj, value) {
obj[value.id] = value;
return obj;
}, {});
var a2_ = a2.reduce(function(obj, value) {
obj[value.id] = value;
return obj;
}, {});
// Then use extend with those two converted objects
var result = angular.extend([], a1_, a2_).splice(1)
Notes:
For compatibility, reduce may not work.
The after array will replace the previous one. This is because of implementation of extend in Angular.

JSON/Javascript: return INDEX of array object containing a certain property

Given a JSON object such as this:
{
"something": {
"terms": [
{
"span": [
15,
16
],
"value": ":",
"label": "separator"
},
{
"span": [
16,
20
],
"value": "12.5",
"label": "number"
}
],
"span": [
15,
20
],
"weight": 0.005,
"value": ":12.5"
}
}
I asked a question about parsing the object out where label: number here:
JSON/Javascript: return which array object contains a certain property
I got a sufficient answer there (use filter()), but now need to know the original index of the object.
This issue seems to have the answer, but I simply don't know enough about javascript to translate it into something useful for my particular problem.
The following code successfully returns the object. Now I need to modify this to return the original index of the object:
var numberValue, list = parsed.something.terms.filter(function(a){
return a.label==='number';
});
numberValue = list.length ? list[0].value : -1;
This needs to be a pure javascript solution, no external libraries, etc.
I don't think you can modify the filter solution as within the filter you've lost the indexes.
The solution you've linked to uses the angular external library.
So here is a pure JS solution:
var numberValue = parsed.something.terms
.map(function(d){ return d['label']; })
.indexOf('number');
Array.prototype.indexOf()
Array.prototype.map()
Use forEach and collect the indices of objects that satisfy the a.label==='number' predicate :
var target = parsed.something.terms;
var list = [];
target.forEach(function(element, index){
if (element.label==='number') {
list.push(index)
};
});
var numberValue = list.length ? target[list[0]].value : -1;
console.log(list); // [1]
console.log(numberValue); // 12.5

Ng-Table ng-repeat on nested values

I have this list i wanted to display on ng-table.
$scope.list = [
{
"moduleId": 1,
"name": "Perancangan",
"level": 0,
"childs": [
{
"moduleId": 12,
"name": "Perancangan Sektor",
"level": 1,
"childs": [],
"links": [
{
"rel": "self",
"href": "http://103.8.160.34/mrf/modules/1"
}
]
}
]
},
{
"moduleId": 2,
"name": "Pengurusan Pengguna dan Peranan",
"level": 0,
"childs": [
{
"moduleId": 17,
"name": "Pengurusan Pengguna",
"level": 1,
"childs": [],
"links": []
},
{
"moduleId": 18,
"name": "Operasi Peranan",
"level": 1,
"childs": [],
"links": []
}
],
"links": [
{
"rel": "self",
"href": "http://103.8.160.34/mrf/modules/2"
}
]
}
];
I wanted the list.childs to be the rows in the table with the list.name as grouping, i'd used ng-repeat to but doesn't work. The most i could do is display it as td. What im looking at is
Perancangan (header)
Perancangan Sektor
Pengurusan Pengguna dan Peranan
Here is the plunker
http://plnkr.co/edit/77t5id3WOmbl2GSqYKh2?p=preview
There seems to be at least two ways you could accomplish this. The first might be more simple but skirts the question you posed. Massage the list[] into a flattened and simplified array tailored for this table's view. You would then ng-repeat over that array.
That is really a dodge though and completely avoids your question. More directly to your question you could try to use nested ng-repeat's but those are pretty tricky. See: http://vanderwijk.info/blog/nesting-ng-repeat-start/
Finally, the approach that seems to best address you're question in both intent and spirit is to use a custom filter. I've written an example fiddle that should demonstrate the idea.
app.filter('flatten', function() {
// Because this filter is to be used for an ng-repeat the filter function
// must return a function which accepts an entire list and then returns
// a list of filtered items.
return function(listItems) {
var i,j;
var item, child;
var newItem;
var flatList = [];
// Begin a loop over the entire list of items provided by ng-repeat
for (i=0; i<listItems.length; i++) {
var item = listItems[i];
// Construct a new object which contains just the information needed
// to display the table in the desired way. This means we just extract
// the list item's name and level properties
newItem = {};
newItem.name = item.name.toUpperCase();
newItem.level = item.level;
// Push the level 0 item onto the flattened array
flatList.push(newItem);
// Now loop over the children. Note that this could be recursive
// but the example you provided only had children and no grandchildren
for (j=0; j<item.childs.length; j++) {
child = item.childs[j];
// Again create a new object for the child's data to display in
// the table. It also has just the name and level.
newItem = {};
newItem.name = child.name;
newItem.level = child.level;
flatList.push(newItem);
}
}
// Return the newly generated array that contains the data which ng-repeat
// will iterate over.
return flatList;
};
});

How to create an JSON array like this in javascript

What is the best way to create an array that looks like the following:
[
{
"id":"1",
"value": true
},
{
"id":"3",
"value": false
},
{
"id":"5",
"value": true
},
{
"id":"6",
"value": false
},
{
"id":"9",
"value": true
},
]
My code:
//add to array
thing = {
"id" : 1,
"value" : "true"
};
thingArray.push(thing);
It does not seem to be properly formatted when I put the output in a JSON validator.
As I commented further up, make sure you're actually serializing it to JSON at some point. In your code example you're simply working with a JavaScript object, which isn't the same thing as JSON. Here's an example:
// start with a regular JavaScript array
var array = [];
// push some regular JavaScript objects to it
array.push({
id: 1,
value: true
});
array.push({
id: 2,
value: false
});
// serialize your JavaScript array into actual JSON
var json = JSON.stringify(array);
// do whatever you want with it...
console.log(json);
Here's a JSBin example.
Your code is fine. Here's some more code to get you started:
var arr = [];
arr.push({"id": 1, "value": "true"});
arr.push({"id": 2, "value": "false"});
console.dir(arr);
http://jsfiddle.net/gg014w0h/
You can run that fiddle and then check your console output. You'll see the contents of the array pretty clearly.
JSON validators will not like the trailing comma of the array. There is a difference between console.log(array) and console.log(JSON.stringify(array)). You may want to use the latter.
Also note that booleans are allowed in JSON:
"value": "true",
"value": true
Those are both valid and they mean different things.

Categories