javascript parsing json - javascript

I have a problem with javascript, im calling an ajax method that returns this string:
{
"ObjectResponse": {
"Operation": "OK",
"Response": "SUCCESS",
"Message": "List of AAA Found",
"List": [
{
"keySource": "gat\/images\/images_set\/apple.jpg",
"idSiteKey": "1",
"text": "Apple"
},
{
"keySource": "gat\/images\/images_set\/cat.jpg",
"idSiteKey": "2",
"text": "Cat"
},
{
"keySource": "gat\/images\/images_set\/coffee.jpg",
"idSiteKey": "3",
"text": "Coffee"
},
{
"keySource": "gat\/images\/images_set\/dog.jpg",
"idSiteKey": "4",
"text": "Dog"
},
{
"keySource": "gat\/images\/images_set\/horse.jpg",
"idSiteKey": "5",
"text": "Horse"
},
{
"keySource": "gat\/images\/images_set\/police.jpg",
"idSiteKey": "6",
"text": "Police"
},
{
"keySource": "gat\/images\/images_set\/tree.jpg",
"idSiteKey": "7",
"text": "Tree"
}
]
}
}
I assing the content in this way:
xhr.onreadystatechange = ensureReadiness;
....
responseText = xhr.responseText;
If i try to parse it on javascript with:
response = JSON.parse(responseText);
if I acces a property such response.ObjectResponse.Operation I do get the right content.. but when I try to access the List it allways brakes
and if I try the same String but instead of calling the service I assign the content to a var it works I do can access the List
var myTemporalString ='{"ObjectResponse":{"Operation":"OK","Response":"SUCCESS","Message":"List of Keys Found","List":...';
response.JSON.parse(myTemporalString);
Any suggestion why this could be happening?

You can try this way,
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
try{
var mJsonData = JSON.parse(xhr.responseText);
}catch(err){
console.log(err);
alert(err);
return;
}
for(i=0;i<jsondata.ObjectResponse.List.length;i++){
console.log(jsondata.ObjectResponse.List[i].text);
console.log(jsondata.ObjectResponse.List[i].keySource);
console.log(jsondata.ObjectResponse.List[i]. idSiteKey);
}
}
}
}

Use a loop!
var array = response.ObjectResponse.List;
var len = array.length;
for(i=0; i<len; i++) {
//Use array[i] to access the list
array[i].keySource
array[i].idSiteKey
array[i].text
}

Related

Delete the json object recursively using id

I wanted to delete the entire json Object if it matches the id, thus keep the structure of the json consistent. My sample json looks something like this:
{
"menu": {
"id": "1",
"value": "File",
"popup": {
"children": [{
"value": "New",
"onclick": "Some click value",
"id": "2"
},
{
"value": "Open",
"onclick": "OpenDoc()",
"id": "3"
},
{
"value": "Close",
"onclick": "CloseDoc()",
"id": "4"
}
]
}
}
}
I want to delete the entire object if the id matches. My code looks something like this
static deleteJsonObject(myJson, objectId) {
for(var key in myJson) {
if (_.isArray(myJson[key])) {
if(myJson[key].length == 0) {
return
}
if(objectId == myJson['id']) {
delete myJson[key]
}
this.deleteJsonObject(myJson[key], objectId);
} else if (_.isObject(myJson[key])) {
if(objectId == myJson['id']) {
delete myJson[key]
}
this.deleteJsonObject(myJson[key], objectId);
}
else if (_.isString(myJson[key])) {
if(objectId == myJson['id']) {
delete myJson[key]
}
}
}
return myJson
}
The problem with my code is that it just deletes the id rather than the entire object if its a child element. Any help is appreciated. Note that I dont want to have empty objects after deletion. It should remove the object entirely from the json. No empty objects or null objects.
A safe way to accomplish what you want is to perform a Depth-first search in your tree, deleting the whole object if the id match.
const data = {
"menu": {
"id": "1",
"value": "File",
"popup": {
"children": [{
"value": "New",
"onclick": "Some click value",
"id": "2"
},
{
"value": "Open",
"onclick": "OpenDoc()",
"id": "3"
},
{
"value": "Close",
"onclick": "CloseDoc()",
"id": "4"
}
]
}
}
}
const deleteByID = (tree, id) =>
{
// First we iterate every element of the object
for (const key in tree)
{
const node = tree[key]
// If the element id matches we delete the whole element
if (node.id == id)
{
// If the parent of this element is a Array, we must remove it with splice
if (tree instanceof Array)
{
tree.splice(key, 1)
}
// Else, we can use the delete operator to delete the property
else
{
delete tree[key]
}
}
// If the element id don't match (or the element doesn't have a id property), we recursively iterate all it's properties
else if (typeof node === 'object')
{
deleteByID(node, id)
}
}
}
deleteByID(data, 3)
console.log(data)
Try this :
var obj = {
"menu": {
"id": "1",
"value": "File",
"popup": {
"children": [{
"value": "New",
"onclick": "Some click value",
"id": "2"
},
{
"value": "Open",
"onclick": "OpenDoc()",
"id": "3"
},
{
"value": "Close",
"onclick": "CloseDoc()",
"id": "4"
}
]
}
}
};
var id = "2";
function deleteObject(obj, id) {
if (obj.menu.id === id) {
delete obj.menu;
} else if (Object.keys(obj.menu).includes('popup')) {
var result = obj.menu.popup.children.filter(item => {
if (item.id === id) {
obj.menu.popup.children.splice(obj.menu.popup.children.indexOf(item), 1);
}
});
}
return obj;
}
var res = deleteObject(obj, id);
console.log(res);

Manipulating javascript object with underscore

I have a Javascript object with a format like below
"items":
{
"Groups":[
{
"title":"group 1",
"SubGroups":[
{
"title":"sub1",
"id" : "1",
"items":[
{
"title":"Ajax request 1",
},
{
"title":"Ajax request 2",
}
]
},
{
"title":"sub2",
"id" : "2",
"items":[
{
"title":"Ajax request 3",
},
{
"title":"Ajax request 4",
}
]
}
]
}
]
There are n 'Groups', n 'subGroups' and n 'items'.
What I want to do firstly is get all the items from a particular group based on id. This is achieved using:
_.each(items.Groups, function(o) {
result = _.where(o.SubGroups, {
'id': '1'
});
});
which returns
"items":[{"title":"Ajax request 1",},{"title":"Ajax request 2",}]
Then I want to get the rest of the data, excluding the items and parent group I have just retrieved.
I tried this:
_.each(items.Groups, function(o) {
arr = _.without(o.SubGroups, _.findWhere(o.SubGroups, {id: '2'}));
});
But this only returns me the items like this:
{
"title":"sub2",
"id" : "2",
"items":[{"title":"Ajax request 3"},{"title":"Ajax request 4",}]
}
whereas what I need is this:
"items":
{
"Groups":[
{
"title":"group 1",
"SubGroups":[
{
"title":"sub2",
"id" : "2",
"items":[
{
"title":"Ajax request 3",
},
{
"title":"Ajax request 4",
}
]
}
]
}
]
Just try this:
_.each(items.Groups, function(o) {
arr = _.without(o, _.findWhere(o.SubGroups, {id: '2'}));
});
o should be enough => you want to get Groups and not SubGroups.
Following is a pure JS implementation:
JSFiddle.
var data = {
"Groups": [{
"title": "group 1",
"SubGroups": [{
"title": "sub1",
"id": "1",
"items": [{
"title": "Ajax request 1",
}, {
"title": "Ajax request 2",
}]
}, {
"title": "sub2",
"id": "2",
"items": [{
"title": "Ajax request 3",
}, {
"title": "Ajax request 4",
}]
}]
}]
}
var items = [];
var group = [];
data.Groups.forEach(function(o) {
var _tmp = JSON.parse(JSON.stringify(o));
_tmp.SubGroups = [];
o.SubGroups.forEach(function(s) {
if (s.id == "1") {
items.push(s.items);
} else {
_tmp.SubGroups.push(s);
group.push(_tmp)
}
});
});
function printObj(label, obj) {
document.write(label + "<pre>" + JSON.stringify(obj, 0, 4) + "</pre>")
}
printObj("group", group);
printObj("items", items);
Using underscore and using your logic to filter all subgroups:
//array to store subgroup with ID 1
var results = [];
var d = _.each(data.items.Groups, function(o) {
result = _.where(o.SubGroups, {
'id': '1'
});
//add to results array
results.push(result);
});
//make a clone of the earlier object so that you get the parent structure.
var data1 = _.clone(data);
//set the filtered results to the group
data1.items.Groups = results;
//your data as you want
console.log(data1)
Working code here

filter result using 2 JSON

This is my saved localstorage,
[{"industry_Id":1,"merchant_id":2}]
I want to filter below result, to get HP.
{
"industries": [
{
"id": 1,
"name": "oil and gas",
"merchant": [
{
"id": 1,
"name": "ABC",
},
{
"id": 2,
"name": "DEF",
},
{
"id": 3,
"name": "GHJ",
}
]
},
{
"id": 2,
"name": "IT",
"merchant": [
{
"id": 1,
"name": "Apple",
},
{
"id": 2,
"name": "HP",
},
{
"id": 3,
"name": "Google",
}
]
}
]
}
I thought of using multiple $.each but it have to iterate few times and it's quite redundant.
I would prefer using Javascript for loop, that way you can skip iterating over every object once required element is found.
Without jQuery (using for)
var i, j, merchant = null;
for(i = 0; i < data['industries'].length; i++){
if(data['industries'][i]['id'] == arg[0]['industry_Id']){
for(j = 0; j < data['industries'][i]['merchant'].length; j++){
if(data['industries'][i]['merchant'][j]['id'] == arg[0]['merchant_id']){
merchant = data['industries'][i]['merchant'][j];
break;
}
}
if(merchant !== null){ break; }
}
}
With jQuery (using $.each)
var merchant_found = null;
$.each(data['industries'], function(i, industry){
if(industry['id'] == arg[0]['industry_Id']){
$.each(industry['merchant'], function(i, merchant){
if(merchant['id'] == arg[0]['merchant_id']){
merchant_found = merchant;
}
return (!merchant_found);
});
}
return (!merchant_found);
});
var arg = [{"industry_Id":1,"merchant_id":2}];
var data = {
"industries": [
{
"id": 1,
"name": "oil and gas",
"merchant": [
{
"id": 1,
"name": "ABC",
},
{
"id": 2,
"name": "DEF",
},
{
"id": 3,
"name": "GHJ",
}
]
},
{
"id": 2,
"name": "IT",
"merchant": [
{
"id": 1,
"name": "Apple",
},
{
"id": 2,
"name": "HP",
},
{
"id": 3,
"name": "Google",
}
]
}
]
};
var i, j, merchant = null;
for(i = 0; i < data['industries'].length; i++){
if(data['industries'][i]['id'] == arg[0]['industry_Id']){
for(j = 0; j < data['industries'][i]['merchant'].length; j++){
if(data['industries'][i]['merchant'][j]['id'] == arg[0]['merchant_id']){
merchant = data['industries'][i]['merchant'][j];
break;
}
}
if(merchant !== null){ break; }
}
}
console.log(merchant);
document.writeln("<b>Without jQuery:</b><br>");
document.writeln((merchant !== null) ? "Found " + merchant['name'] : "Not found");
var merchant_found = null;
$.each(data['industries'], function(i, industry){
if(industry['id'] == arg[0]['industry_Id']){
$.each(industry['merchant'], function(i, merchant){
if(merchant['id'] == arg[0]['merchant_id']){
merchant_found = merchant;
}
return (!merchant_found);
});
}
return (!merchant_found);
});
console.log(merchant_found);
document.writeln("<br><br><b>With jQuery:</b><br>");
document.writeln((merchant_found) ? "Found " + merchant_found['name'] : "Not found");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
selectors.map(function(selector) {
return data.industries.filter(function(industry) {
return industry.id == selector.industry_Id;
})[0].merchant.filter(function(merchant) {
return merchant.id == selector.merchant_id;
})[0].name;
});
// => DEF
If you want "HP", you want industry 2, not industry 1.
.filter(...)[0] is not really optimal. You could use .find(...), but that is not yet universally supported. Or you could use plain old JavaScript and write for loops instead to make it fast. Or you could use objects with ID keys instead of arrays to make lookups faster.
When it comes into a position where collection of data is what you're processing, I suggest you to take a look at underscore.js. It's not optimal choice for the best performance but it does make you code more readable and makes more sense especially when compared with loop.
Say data is a variable which stores your JSON data.
Try this:
// Given this selector criteria
var select = [{"industry_Id":1,"merchant_id":2}];
function filterByCriteria(criteria, data){
var match = [];
_.each(criteria, function(crit){
function matchIndustry(rec){ return rec.id===crit.industry_Id }
function matchMerchant(rec){ return rec.id===crit.merchant_id }
// Filter by industry id
var industry = _.first(_.where(data.industry, matchIndustry));
// Filter by merchant id
var merchant = _.where(industry.merchant, matchMerchant);
_.each(merchant, function addToMatchResult(m){
match.push(m.name);
});
});
return match;
}
var filteredData = filterByCriteria(select, data);
From snippet above, any merchants which match the search criteria will be taken to the match list. Is it more readable to you?
Do you even need numerical id's? Gets super easy when you don't.
/*
{
"industry": {
"oil and gas":{
"merchant": {
"ABC": {
"name": "ABC oil"
},
"DEF": {
"name": "DEF gas"
},
"GHJ" :{
"name": "GHJ oil and gas"
}
}
},
"IT": {
"merchant": {
"Apple" : {
"name": "Apple computers"
},
"HP": {
"name": "Hewlett Packard"
},
"Google": {
"name": "Google. Maw haw haw"
}
}
}
}
}
*/
var data = '{"industry": {"oil and gas":{"merchant": {"ABC": {"name": "ABC oil"},"DEF": {"name": "DEF gas"},"GHJ" :{"name": "GHJ oil and gas"}}},"IT": {"merchant": {"Apple" : {"name": "Apple computers"},"HP": {"name": "Hewlett Packard"},"Google": {"name": "Google. Maw haw haw"}}}}}';
data = JSON.parse(data);
var merchant = data.industry['IT'].merchant['HP'];
alert(merchant.name);
//console.log(merchant.name);

programmatically add object properties of arrays

[
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
]
how can I insert into specified array by inspecting its properties values? says I want to add a assoc object into uId = 3, how can I do that? or it's not possible technically?
This is also possible using array.map (Added to the ECMA-262 standard in the 5th edition):
array.map(function(i){
if(i.uId == 3) i['newprop'] = 'newValue';
});
Example Here.
Update: It could be an array
if(i.uId == 3) i['newprop'] = ['newvalue1', 'newvalue2'];
Example2 Here.
They look like JSON data , so json_decode() to an array , search for the UId value and then add the corresponding assoc value and after the end finally wrap them up using json_encode()
foreach($array as $k=>&$arr)
{
if($arr->{'uId'}==2)
{
$arr->{'somecol'}="Hey";
}
}
echo json_encode($array,JSON_PRETTY_PRINT);
OUTPUT :
[
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10",
"somecol": "Hey"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
]
var array = [
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
];
for ( var i = 0; i < array.length; i++ ) {
if ( array[i].uId == 3) {
array[i].someProp = "Hello";
break; // remove this line for multiple updates
}
}
Or you can make a function like this:
function getMatch(data, uid) {
for ( var i = 0; i < data.length; i++ ) {
if ( data[i].uId == 3) {
return data[i];
}
}
}
and use it like this:
getMatch(array, 3).someproperty = 4;
You can use the map function, which executes a function on each element of an array
a.map(function(el) {
if (el.uId == 3) {
el.prop = "value";
}
});
Or you can use the filter function.
// Get the array of object which match the condition
var matches = a.filter(function(x) { return x.uId == 3 });
if (matches.length > 0) {
matches[0].prop = "value";
}

How to print matched and not matched based on matched condtion using angular?

{
"_id": {
"$oid": "5705f793e4b0acd6e2456804a"
},
"Categories": [
{
"mainmodels": [
{
"submodels": [
{
"price": "2000",
"submodelname": "lumia021",
"Remainingphones": "2",
"Bookedphones": "8",
"Numofphones": "10"
},
{
"price": "4000",
"submodelname": "lumia K6",
"Remainingphones": "0",
"Bookedphones": "15",
"Numofphones": "15"
}
],
"Status": "Active",
"modelname": "lumia",
"fromdate": "2016-04-01T16:39:12.051Z",
"todate": "2016-04-31T19:19:44.051Z"
}
],
"brand": "nokia"
}
],
"rank": "1",
"name": "kalasipalaya"
}
I have given my object above i need to check every submodel(here two sumodels is there)Numofphones and Bookedphones are matched . if both(here i given two submodel) Numofphones and Bookedphones are matched i need to print matched otherwise i need to print not matched how can i solve this one help me out .
//This will take to submodel array of object
var _getSubModel = m[0].Categories[0].mainmodels[0].submodels;
var _newArray2 = [];
//Checking if Bookedphones of first object submodel, is same with other objects.
var _newArray = _getSubModel.filter(function(item){
return item.Bookedphones == _getSubModel[0].Bookedphones;
})
// If all the Bookedphones are same then length of _newArray & submodel will be same.
// If same then check for Numofphones
if(_getSubModel.length == _newArray.length){
_newArray2 = _getSubModel.filter(function(item){
return item.Numofphones == _getSubModel[0].Numofphones;
})
// If all Numofphones are same,then length of _newArray2 & submodel will be same
if(_getSubModel.length == _newArray2.length){
console.log('Matched');
}
else{
console.log('Not Matched');
}
}
else{
console.log('Not Matched');
}
Check this jsfiddle
You can use custom filter something like that:
var result = [];
angular.forEach(submodels, function (submodel) {
if(submodel.Numofphones == submodel.Bookedphones)
result.push(submodel);
});
return result;
http://jsfiddle.net/y7r1xe0t/236/
UPDATED: http://jsfiddle.net/y7r1xe0t/237/
return function (submodels, matched_or_not) {
var result = [];
angular.forEach(submodels, function (submodel) {
if(matched_or_not && submodel.Numofphones == submodel.Bookedphones)
result.push(submodel);
else if(!matched_or_not && submodel.Numofphones != submodel.Bookedphones)
result.push(submodel);
});
return result;
};
Filter will return matched object when you send true.

Categories

Resources