parsing json array in javascript with unknown field names - javascript

I have found a lot of threads here on StackOverflow that talk about parsing json arrays but I can't seem to figure out how to get back some of the data. Here is what I have...
$('#keyword_form').submit(function(e){
var gj = $.post('employee_search.php',$('#keyword_form').serialize(),function(data){
if(!data || data.status !=1 )
{
alert(data.message);
return false;
}
else
{
alert(data.message);
}
},'json');
e.preventDefault();
});
The json data being sent to it looks like this...
{
"status":1,
"message":"Query executed in 9.946837 seconds.",
"usernames_count":{
"gjrowe":5,
"alisonrowe":4,
"bob":"1"
}
}
As my function shows I can do alert(data.message); but how can I access the usernames_count data?
My confusion comes from the fact that the data has no name/label. bob is a username and 1 is the returned count associated with that username
If I do alert(usernames_count); I get back [object Object]
If I do alert(usernames_count[0]); I get back undefined
I am sure I should be doing something with JSON.parse(); but I haven't gotten it right yet

You can use Object.keys or a for…in loop – remember in that case to use hasOwnProperty:
var users = data.usernames_count;
Object.keys(users).forEach(function(user) {
console.log(user, users[user]);
});

Try this:
$.each(data.usernames_count, function(username, val) {
alert(username+" has a value of "+val);
});

It sounds like your question is how to iterate over the entries in the usernames_count object. You can do that like so:
var key = '';
for(key in data.usernames_count) {
//check that this key isn't added from the prototype
if(data.usernames_count.hasOwnProperty(key) {
var value = data.usernames_count[key];
//do something with the key and value
}
}

Related

JQuery treating my non-empty array as empty?

Very simply I have built a multi-dimensional array across a long section of script and at the end I want to loop through each level and do something. I have logged the array out in the console and can see everything as it should be, but the console then tells me the array length is 0 and sure enough if I .length it is also tells me the length is 0, so my JQuery each isn't firing. I can't understand what one can do to make it behave like this. I am absolutely stumped!
This is the console:
Here is the JQuery, although the array/object is built over so much script and ajax calls that I've tried to only put in the bits that count...
var field_layers = [];
function blah_blah() {
do_api_call("api_call_url_here")
.done(function(response, textStatus, xhr) {
var map_layers = response;
$(map_layers).each(function(map_layers_key, map_layers_detail) {
var datalayer_id = map_layers_detail.Layer.DataLayerId;
// add field ids to array:
field_layers["field_id_"+map_layers_detail.Layer.FieldId] = [];
do_api_call("api_call_url_here/"+datalayer_id)
.done(function(response, textStatus, xhr) {
// create an empty array for field layers:
field_layers["field_id_"+map_layers_detail.Layer.FieldId]["layer_id_"+datalayer_id] = [];
var map_layer_zones = response;
$(map_layer_zones).each(function(map_layer_zone_key, map_layer_zone_detail) {
// Add the zones to the layer
field_layers["field_id_"+map_layers_detail.Layer.FieldId]["layer_id_"+datalayer_id].push({
"zone_id":zone.DataLayerZoneId,
"title":zone.DataLayerZoneId+" title here"
});
});
});
});
});
}
function go_to_field(field_id) { // this is what gives me the console screenshot
console.log("field_id: "+field_id);
console.log(field_layers["field_id_"+field_id]);
console.log(field_layers["field_id_"+field_id].length);
}
Try changing your field_layers = [] to be an object instead of an array: field_layers = {}. I think if you change each place you are initializing an empty array to initializing an empty object, then your code should work as-is.
Notice the difference between square brackets and curly braces.
With you coming from a PHP background, you can think of Javascript objects (the {}) as associative (or named) arrays in PHP.
So the final code would look like:
var field_layers = {};
function blah_blah() {
do_api_call("api_call_url_here")
.done(function(response, textStatus, xhr) {
var map_layers = response;
$(map_layers).each(function(map_layers_key, map_layers_detail) {
var datalayer_id = map_layers_detail.Layer.DataLayerId;
// add field ids to object:
field_layers["field_id_"+map_layers_detail.Layer.FieldId] = {};
do_api_call("api_call_url_here/"+datalayer_id)
.done(function(response, textStatus, xhr) {
var map_layer_zones = response;
$(map_layer_zones).each(function(map_layer_zone_key, map_layer_zone_detail) {
// Add the zones to the layer
field_layers["field_id_"+map_layers_detail.Layer.FieldId]["layer_id_"+datalayer_id] = {
"zone_id":zone.DataLayerZoneId,
"title":zone.DataLayerZoneId+" title here"
}; // notice the assignment of object literal here
});
});
});
});
}
function go_to_field(field_id) { // this is what gives me the console screenshot
console.log("field_id: "+field_id);
console.log(field_layers["field_id_"+field_id]);
console.log(field_layers["field_id_"+field_id].length);
}
I haven't tested this, but I think it should work.

Javascript function always returns 0

I am writing a function which searches for a value in my IndexedDB and if it finds one, then it should return 1, else it should return 0. The problem is that it always returns 0 though the value exists in a database (variable arr is incremented, but 0 is returned as a result). The code is as follows:
searchAllValues: function(store, type)
{
var arr = 0;
AAA.initDb(function()
{
var obj = {};
AAA.aaaDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
if(storeresult.value.value == type ){
arr++;
}else{console.log('value NOT found');}
storeresult ? (obj[storeresult.key] = storeresult.value.value, storeresult["continue"]()) : callback(obj)
}
});if(arr!=0){return 1}else{return 0}
}
EDIT_1:
Ok, I have refactored the code as follows:
addInfo: function(store, type, info)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
console.log('value of storeresult==>'+storeresult.value.value);
if(storeresult.value.value == info)
{
arr.push(storeresult.value.values);return;//If it finds something it should stop here, no more search or anything to be done
}else
{
console.log('continuing..');
storeresult['continue']();
}
console.log('arr length==> '+arr.length);//If it finds nothing after the looping the whole DB, I want it to print this statement, only once (to send it to my DB actually but sending code is omitted for simplicity).
}
}
Instead I get console.log('arr length==>') statement executed 2 times, for every key in my object store (there are 2 of them actually). So it is doing the code when it finds nothing AND when it finds the value in the DB. Any ideas how to fix it?
Any ideas would be welcome, Thank You
Because by the time the line if(arr!=0){return 1}else{return 0} is executed the db transaction is not complete and value of arr is 0. Though never used indexedDb, but webSql do take some extra miliseconds to read from DB.
Try to put your return logic inside the onsuccess function where you incrementing the arr. You can simply test it by printing value of arr just before your return logic
You need to learn about how to write asynchronous javascript. There are several other indexedDB questions where there are explanations as to why this happens.
For example: Uncaught TypeError: Cannot read property 'transaction' of null with an indexeddb
function addInfo(store, type, info, next)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
console.log('value of storeresult==>'+storeresult.value.value);
if(storeresult.value.value == info)
{
arr.push(storeresult.value.values);
next(arr);//If it finds something it should stop here, no more search or anything to be done
}else
{
console.log('continuing..');
storeresult.continue();
}
console.log('arr length==> '+arr.length);//If it finds nothing after the looping the whole DB, I want it to print this statement, only once (to send it to my DB actually but sending code is omitted for simplicity).
}
}
Added an extra parameter called 'next' to your the addInfo function.
'next' param is the very last function called if the condition (storeresult.value.value == info) is true.
The next function which you create, will use the 'arr' variable and do whatever with it
your 'return statement' doesnt work the sameway with asynchronous functions, would highly advice you search up asynchronous functions to get a gist of how its different to regular functions
This is how you would call your newly edited function:
addInfo(store,type,info,function(arr){
//do something with arr
})
Note that you have a potential state which would break your code
what if the cursor reaches the end of its iterations and never meets that condition (storeresult.value.value == info). storeresult would be null, and the check for the condition (null.value.value == info) will throw an exception
correction:
function addInfo(store, type, info, next)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store){
var storeresult = store.target.result;
if(storeresult){
if(storeresult.value.value == info){
arr.push(storeresult.value.values);
next(arr);
}else storeresult.continue();
}else next();
}
}
And when you call it you handle the scenario whereby arr == null
addInfo(store,type,info,function(arr){
if(arr){
//do something with arr
}else{
//do somethingelse when arr == null
}
})

Populating array with nested $each functions and conditionals in Angular with jQuery

I'm having a json object I get from a get request in an angular application. It gives me two main attributes data and included. The included object is somehow a relationship with the data object. For example data shows messages and included the senders of those messages. I managed to associate every message with the sender by checking if an attribute from the data object is the same with another attribute in the included object. here is my code
$http.get('data.json').then(
function(jsonAPI) {
console.log(jsonAPI);
var dataObj = {};
var messages = [];
$.each(jsonAPI.data.data, function(x, data) {
dataObj[x] = data;
$.each(jsonAPI.data.included, function(y, included) {
if (data.relationships.sender.data.id == included.id) {
dataObj[x].sender = included;
}
});
messages.push(dataObj[x]);
});
$scope.newMessages = messages;
},
function(errorResponse) {
// todo handle error.
}
);
I create a new array that contains all the data object and also sender's information under the sender attribute. The problem is that a new relationship is added called user_data_template. I want with a similar way to be able to pass to the messages array the corresponding user_data_template data. How can I change the above nested $each function to achieve that?
Here is a working plunker
I managed to find the solution. I had to change the code to the following:
$.each(jsonAPI.data.data, function(x, data) {
dataObj[x] = data;
$.each(jsonAPI.data.included, function(y, included) {
if(data.relationships.sender.data.id == included.id && included.type == "user") {
dataObj[x].sender = included;
}
if(data.relationships.user_data_template.data !== undefined) {
if(data.relationships.user_data_template.data.id == included.id && included.type == "user_data_template") {
dataObj[x].question = included;
}
}
});
messages.push(dataObj[x]);
});
And the new plunker

How to extract data from array in javascript

I have an object (array type) ,its console representation looks like following image . please see the image
This array is created by restangulr using following code ,
restangularProvider.addResponseInterceptor(function (data, operation, what, url, response, deferred) {
if (operation == "getList") {
var extractedData;
extractedData = data.result;
extractedData.paginginfo = data.paginginfo;
return extractedData;
}
if (operation != "get") {
var item = { status: response.status };
feedBackFactory.showFeedBack(item);
}
return response.data;
});
How can I read the elements from this array, I want to extract properties like paginginfo ,also object collection
// The EDIT :1 js libraries I used here angularjsu 1.3.4, and restangular 1.4
My app.js : here I configured rest angular provider
restangularProvider.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
if (operation == "getList") {
var extractedData;
extractedData = data.result;
extractedData.paginginfo = data.paginginfo;
return extractedData;
}
if (operation != "get") {
var item = {
status: response.status
};
feedBackFactory.showFeedBack(item);
}
return response.data;
});
// according to my knowledge this function will intercept every ajax call (api calls) and modify the response , unfortunately I need to apply custom modification because the getlist method must return collection but my api returning object, so according to restangular ,the above code is the possible solution, and here its fine its fetching the data.
userservice.js : this is angular service which using restangular
function(restangular) {
var resourceBase = restangular.all("account");
this.getUsers = function(pagenumber, recordsize) {
var resultArray = resourceBase.getList({
page: pagenumber,
size: recordsize
}).$object;
};
};
according to my knowledge .$object in restangulr resolve the promise and bring back the data, also I am getting the resultArray its looks like in the image in the console, here I can log this array so I think I got all the data from server and filled in this object. I applied some array accessing techniques available jquery and JavaScript like index base accessing , associate accessing but I am getting undefined ie.
resultArray[1] //undifiend;
In angular you can use angular.forEach(items, function(item){ //your code here});
Where items is the array you want to traverse.
If you want to access to one specific position use [], for example var item= items[5].
Then you can do item.property.
UPDATE
Your problem is that you are setting properties in an Array JS Object:
extractedData.paginginfo = data.paginginfo;
You should return the object data like it is and in your controller do something like:
var results= data.result;
var pagInfo= data.paginationInfo;
angular.forEach(results,function(result){});
It looks like the array is numerically indexed (0..1..5); you should be able to simply iterate through it using ForEach (in Angular) or .each (in Jquery).
Something like (JQuery):
$.each(array, function(key, value)
{
// key would be the numerical index; value is the key:value pair of the array index's element.
console.log(value.firstname); // should print the firstname of the first element.
});
First of all, as I said in the comments, you shouldn't be attaching named properties to arrays. Return an object thact contains what you need:
if (operation == "getList") {
return { values: data.result, paging: data.pagingInfo };
}
The getList() method returns a promise, so you need to use that:
this.getUsers = function(pagenumber, recordsize) {
resourceBase.getList({
page: pagenumber,
size: recordsize
}).then(function (data) {
console.log(data.values[0]);
console.log(data.paging.totalRecords);
});
};

Searching for items in a JSON array Using Node (preferably without iteration)

Currently I get back a JSON response like this...
{items:[
{itemId:1,isRight:0},
{itemId:2,isRight:1},
{itemId:3,isRight:0}
]}
I want to perform something like this (pseudo code)
var arrayFound = obj.items.Find({isRight:1})
This would then return
[{itemId:2,isRight:1}]
I know I can do this with a for each loop, however, I am trying to avoid this. This is currently server side on a Node.JS app.
var arrayFound = obj.items.filter(function(item) {
return item.isRight == 1;
});
Of course you could also write a function to find items by an object literal as a condition:
Array.prototype.myFind = function(obj) {
return this.filter(function(item) {
for (var prop in obj)
if (!(prop in item) || obj[prop] !== item[prop])
return false;
return true;
});
};
// then use:
var arrayFound = obj.items.myFind({isRight:1});
Both functions make use of the native .filter() method on Arrays.
Since Node implements the EcmaScript 5 specification, you can use Array#filter on obj.items.
Have a look at http://underscorejs.org
This is an awesome library.
http://underscorejs.org/#filter
edited to use native method
var arrayFound = obj.items.filter(function() {
return this.isRight == 1;
});
You could try find the expected result is using the find function, you can see the result in the following script:
var jsonItems = {items:[
{itemId:1,isRight:0},
{itemId:2,isRight:1},
{itemId:3,isRight:0}
]}
var rta = jsonItems.items.find(
(it) => {
return it.isRight === 1;
}
);
console.log("RTA: " + JSON.stringify(rta));
// RTA: {"itemId":2,"isRight":1}
Actually I found an even easier way if you are using mongoDB to persist you documents...
findDocumentsByJSON = function(json, db,docType,callback) {
this.getCollection(db,docType,function(error, collection) {
if( error ) callback(error)
else {
collection.find(json).toArray(function(error, results) {
if( error ) callback(error)
else
callback(null, results)
});
}
});
}
You can then pass {isRight:1} to the method and return an array ONLY of the objects, allowing me to push the heavy lifting off to the capable mongo.

Categories

Resources