I am trying to use the following code to create a list of client names from some json returned from an Ajax call.
The data is as follows:
{"status":1,"data":{"clients":[{"ClientID":"1","AccountID":"1","ClientName":"Access Loan Mitigation","Active":"1"},{"ClientID":"2","AccountID":"1","ClientName":"Big Time Business","Active":"1"},{"ClientID":"3","AccountID":"1","ClientName":"Bill Releford","Active":"1"},{"ClientID":"4","AccountID":"1","ClientName":"Bonnie Silverman","Active":"1"},{"ClientID":"5","AccountID":"1","ClientName":"Dear Holdings","Active":"1"},{"ClientID":"6","AccountID":"1","ClientName":"Calm Dental","Active":"1"},{"ClientID":"7","AccountID":"1","ClientName":"Eva Field","Active":"1"},{"ClientID":"8","AccountID":"1","ClientName":"First Independent Pictures","Active":"1"},{"ClientID":"9","AccountID":"1","ClientName":"Gallery 825","Active":"1"},{"ClientID":"10","AccountID":"1","ClientName":"Greenway Arts Alliance","Active":"1"},{"ClientID":"11","AccountID":"1","ClientName":"International Strategy Group","Active":"1"},{"ClientID":"12","AccountID":"1","ClientName":"Ramtin","Active":"1"},{"ClientID":"13","AccountID":"1","ClientName":"Spabro","Active":"1"},{"ClientID":"14","AccountID":"1","ClientName":"LMGA","Active":"1"},{"ClientID":"15","AccountID":"1","ClientName":"Main Street Business Association","Active":"1"},{"ClientID":"16","AccountID":"1","ClientName":"Rabbit Animation","Active":"1"},{"ClientID":"17","AccountID":"1","ClientName":"Rooms & Gardens","Active":"1"},{"ClientID":"18","AccountID":"1","ClientName":"Summertime","Active":"1"},{"ClientID":"19","AccountID":"1","ClientName":"Sue Shellock","Active":"1"},{"ClientID":"20","AccountID":"1","ClientName":"Susan Gates","Active":"1"},{"ClientID":"21","AccountID":"1","ClientName":"The Park Entertainment","Active":"1"},{"ClientID":"22","AccountID":"1","ClientName":"Unified Dispatch","Active":"1"},{"ClientID":"23","AccountID":"1","ClientName":"Westside Media Group","Active":"1"},{"ClientID":"24","AccountID":"1","ClientName":"YHD","Active":"1"},{"ClientID":"25","AccountID":"1","ClientName":"Discoverfire, Inc.","Active":"1"}]}}
and the code is like so:
for (var Client in o.data.clients) {
$('#list_container').append("<div>"+Client.ClientName+"</div>");
}
Not quite working, and I've tried a few different ways of accessing the ClientName property. Javascript isn't my strongest language, and getting data out of objects just kills me - used to PHP object and arrays.
I'm sure this is simple - can somebody show the right syntax?
Thanks!
Clients is an array so it's better to use jQuery's each on it:
$.each( o.data,clients, function(idx, client) {
// use client.ClientName here
});
That's not quite how the for loop works. An easier, more accurate, and more reliable way to tackle this is to use the traditional for syntax like so:
for (var i = 0; i < o.data.clients.length; i++) {
var client = o.data.clients[i];
$('#list_container').append("<div>"+client.ClientName+"</div>");
}
The for syntax you were using will work, but it's still iterating over indices (not values), and even then it's not limited to just the integer indices in the array — it could also include other properties defined on the array prototype, or even on the particular array object. Iterating using the boring i = 0 syntax is a far better option for traditional arrays like this.
Related
I have a previously created script that is doing API calls to get various info. Using json fetch. Its used to look up(GET) properties of users, groups, etc.
Here is how it prints. console.log(myArray):
[{user={conversion_id=smitht, ship_id=14.0, ship=Mountain , id=989, name=Smith, Todd, id=8745335.0, system_id=796663, login_id=todd.smith#domain.com,, created_at=3055-08-10, //keeps continuing for all users in this account
If I wanted to search the array and return only "name". Is there a better way to accomplish than this? This will print out just the names
for (let i = 0; i < myArray.length; i++){
console.log(myArray[i]['user']['name'])
I'm trying to learn what's possible and how to interact. Any other options to search through array? Most examples have sample arrays written out since mine comes from a response its been difficult to follow those examples.
use find https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
function findByLoginId(loginId) {
const result = myArray.find(user => user.login_id === loginId);
return result?.name;
}
Check to make sure that the fetched data is valid JSON. You should be able to use JSON.parse on the returned data.
I'm calling a JavaScript function that wants an array of things to display. It displays a count, and displays the items one by one. Everything works when I pass it a normal JavaScript array.
But I have too many items to hold in memory at once. What I'd like to do, is pass it an object with the same interface as an array, and have my method(s) be called when the function tries to access the data. And in fact, if I pass the following:
var featureArray = {length: count, 0: func(0)};
then the count is displayed, and the first item is correctly displayed. But I don't want to assign all the entries, or I'll run out of memory. And the function currently crashes when the user tries to display the second item. I want to know when item 1 is accessed, and return func(1) for item 1, and func(2) for item 2, etc. (i.e., delaying the creation of the item until it is requested).
Is this possible in JavaScript?
If I understand correctly, this would help:
var object = {length: count, data: function (whatever) {
// create your item
}};
Then, instead of doing array[1], array[2], et cetera, you'd do object.data(1), object.data(2), and so on.
Since there seems to be a constraint that the data must be accessed using array indexing via normal array indexing arr[index] and that can't be changed, then the answer is that NO, you can't override array indexing in Javascript to change how it works and make some sort of virtual array that only fetches data upon demand. It was proposed for ECMAScript 4 and rejected as a feature.
See these two other posts for other discussion/confirmation:
How would you overload the [] operator in Javascript
In javascript, can I override the brackets to access characters in a string?
The usual way to solve this problem would be to switch to using a method such as .get(n) to request the data and then the implementor of .get() can virtualize however much they want.
P.S. Others indicate that you could use a Proxy object for this in Firefox (not supported in other browsers as far as I know), but I'm not personally familiar with Proxy objects as it's use seems rather limited to code that only targets Firefox right now.
Yes, generating items on the go is possible. You will want to have a look at Lazy.js, a library for producing lazily computed/loaded sequences.
However, you will need to change your function that accepts this sequence, it will need to be consumed differently than a plain array.
If you really need to fake an array interface, you'd use Proxies. Unfortunately, it is only a harmony draft and currently only supported in Firefox' Javascript 1.8.5.
Assuming that the array is only accessed in an iteration, i.e. starting with index 0, you might be able to do some crazy things with getters:
var featureArray = (function(func) {
var arr = {length: 0};
function makeGetter(i) {
arr.length = i+1;
Object.defineProperty(arr, i, {
get: function() {
var val = func(i);
Object.defineProperty(arr, i, {value:val});
makeGetter(i+1);
return val;
},
configurable: true,
enumerable: true
});
}
makeGetter(0);
return arr;
}(func));
However, I'd recommend to avoid that and rather switch the library that is expecting the array. This solution is very errorprone if anything else is done with the "array" but accessing its indices in order.
Thank you to everyone who has commented and answered my original question - it seems that this is not (currently) supported by JavaScript.
I was able to get around this limitation, and still do what I wanted. It uses an aspect of the program that I did not mention in my original question (I was trying to simplify the question), so it is understandable that other's couldn't recommend this. That is, it doesn't technically answer my original question, but I'm sharing it in case others find it useful.
It turns out that one member of the object in each array element is a callback function. That is (using the terminology from my original question), func(n) is returning an object, which contains a function in one member, which is called by the method being passed the data. Since this callback function knows the index it is associated with (at least, when being created by func(n)), it can add the next item in the array (or at least ensure that it is already there) when it is called. A more complicated solution might go a few ahead, and/or behind, and/or could cleanup items not near the current index to free memory. This all assumes that the items will be accessed consecutively (which is the case in my program).
E.g.,
1) Create a variable that will stay in scope (e.g., a global variable).
2) Call the function with an object like I gave as an example in my original question:
var featureArray = {length: count, 0: func(0)};
3) func() can be something like:
function func(r) {
return {
f : function() {featureArray[r + 1] = func(r + 1); DoOtherStuff(r); }
}
}
Assuming that f() is the member with the function that will be called by the external function.
my first time posting a question here, so please let me know if I'm missing any information that is needed. Updated to include desired output.
I'm working on a google app script (basically javascript) and am trying to pull objects from an array of objects and create a new array of objects. I'm using the google base functions for getRowData (these can be found at : https://developers.google.com/apps-script/guides/sheets) to create my initial array of objects. This gives me a row of data similar (A JIRA export if anyone is wondering, with information cut):
{summary=Internal - Fix PuppetFile Jenkins Jobs, progress=1.0, issueType=Story, resolution=Done, timeSpent=3600.0, key=XXXXX-646, watchers=0.0, remainingEstimate=0.0, numberOfComments=1.0, status=Resolved, assignee=XXXXXXXX}
When I run my function:
for (var i = 0; i < issueList.length; i++){
rankList[i] = [issueList[i].summary,issueList[i].storyPoints,issueList[i].epicLink,issueList[i].fixVersions];
}
I get:
[Internal - Fix PuppetFile Jenkins Jobs, 3.0, null, null]
But what I want is:
{summary=Internal - Fix PuppetFile Jenkins Jobs, storyPoints=1.0, epicLink=StoryName, fixVersions=Done}
I'm not getting the key for the value, and I don't understand how the objects are constructed quite well enough to get it to transfer over. I looked at some examples of manipulating the key/value pairs but when I tried it on my own I just got a bunch of undefined. Thank you for any help you can provide.
What you want is probably something like this:
rankList = [];
for (var i = 0; i < issueList.length; i++) {
issue = issueList[i];
rankList.push({
summary: issue.summary,
storyPoints: issue.progress,
epicLink: issue.IDONTKNOW,
fixVersions: issue.resolution
});
}
I don't know what field goes in epicLink, since it wasn't obvious from your example. And I was just guessing about the other fields. But this is the general structure, you just need to make all the correct correspondences.
Use jquery each instead it's much easier to get the keys and value at the same time:
var myarray = [];
$.each(issueList,function(key,value){
console.log(key);
console.log(value);
value.key = key;
myarray.push(value);
});
console.log(myarray);
I have an ajax call that returns a JSON object that is pretty complex and I'm having a hard time sorting it.
My call:
$.post('/reports-ajax',arguments, function(data) {}
The response:
{
"10001":{
"unitname":"Fort Worth",
"discounts":{"12-02-2012":"34.810000","12-03-2012":"20.810000","12-04-2012":"27.040000"},
"gross":{"12-02-2012":"56.730000","12-03-2012":"19.350000","12-04-2012":"66.390000"},
"net":{"12-02-2012":"61.920000","12-03-2012":"98.540000","12-04-2012":"39.350000"},
"discounts_total":82.66,
"gross_total":82.47,
"net_total":99.81,
"number":10001
},
"10002":{
"unitname":"Dallast",
"discounts":{"12-02-2012":"12.600000","12-03-2012":"25.780000","12-04-2012":"47.780000","12-05-2012":"45.210000"},
"gross":{"12-02-2012":"29.370000","12-03-2012":"91.110000","12-04-2012":"60.890000","12-05-2012":"51.870000"},
"net":{"12-02-2012":"16.770000","12-03-2012":"65.330000","12-04-2012":"13.110000","12-05-2012":"06.660000"},
"discounts_total":131.37,
"gross_total":33.24,
"net_total":101.87,
"number":10002
},
"32402":{
"unitname":"Austin",
"discounts":{"12-05-2012":"52.890000","12-02-2012":"22.430000","12-03-2012":"58.420000","12-04-2012":"53.130000"},
"gross":{"12-05-2012":"25.020000","12-02-2012":"2836.010000","12-03-2012":"54.740000","12-04-2012":"45.330000"},
"net":{"12-04-2012":"92.200000","12-05-2012":"72.130000","12-02-2012":"13.580000","12-03-2012":"96.320000"},
"discounts_total":186.87,
"gross_total":161.1,
"net_total":174.23,
"number":32402
}
}
I go over the function with a standard each call and do some awesome stuff with highcharts but now I'm trying to sort the responses by the net_total call and I can't figure it out.
I tried .sort() and it errors out that its not a function. I've been reading for a while but guess I'm not finding the right results. This looked promising: Sorting an array of JavaScript objects but it failed with the .sort is not a function. It seems most .sort are on [] arrays not full objects..
Any help would be greatly appreciated.
Sorting objects doesn't make sense since object keys have no positional value. For example, this:
{ a:1, b:2 }
and this:
{ b:2, a:1 }
are exactly the same object. They're not just similar, they're the same.
Nothing in javascript per se gives object keys any positional value. Some people perhaps are mistaken in the belief that:
for (var key in obj) {
iterates through the object keys in a specific sequence. But this is wrong. You should always assume that the for .. in loop processes object keys in random order, always, all the time.
Obviously, if you're going to write a web browser, you're not going to implement a random number generator to parse a for .. in loop. Therefore most web browsers have an accidental stability to how the for .. in loop processes object keys.
Developers who learn javascript by playing around with the browser may figure out that their browser iterates through objects in alphabetical order for example, or the order the keys were added to the object. But this is totally accidental and cannot be relied upon. The browser vendor may change this behavior in the future without violating any backwards compatability (except with buggy scripts written by people who believe objects have a sort order). Not to mention that different browsers have different implementations of javascript and therefore not necessarily have the same internal key ordering of objects.
All the above is besides the point. "Key sort order" does not make any sense in javascript and any behavior observed is merely implementation detail. In short, javascript object does not have key order, just assume it's random.
Solution
Now, what you're really trying to do is not sort the object (you can't, it doesn't make sense). What you're really trying to do is process the object attributes in a specific order. The solution is to simply create an array (which has sorting order) of object keys and then process the object using that array:
// First create the array of keys/net_total so that we can sort it:
var sort_array = [];
for (var key in Response) {
sort_array.push({key:key,net_total:Response[key].net_total});
}
// Now sort it:
sort_array.sort(function(x,y){return x.net_total - y.net_total});
// Now process that object with it:
for (var i=0;i<sort_array.length;i++) {
var item = Response[sort_array[i].key];
// now do stuff with each item
}
What you have there isn't an array and has no order, so you'll have to transform it into an array so you can give it order.
Vaguely:
var array = [];
$.each(data, function(key, value) {
array.push(value);
});
array.sort(function(a, b) {
return a.net_total - b.net_total;
});
Live Example | Source
As GolezTroi points out in the comments, normally the above would lose the key that each entry is stored under in data and so you'd add it back in the first $.each loop above, but in this case the entries already have the key on them (as number), so there's no need.
Or you can replace the first $.each with $.map:
var array = $.map(data, function(entry) {
return entry;
});
// ...and then sort etc.
...whichever you prefer.
Is there a way to get the name of the first property of a JSON object?
I'd like to do something like this:
var firstProp = jsonObj[0];
edit: I'm getting a JSON object which hold categories of arrays with image
URLs.
like so:
{
"category1":["image/url/1.jpg","image/url/2.jpg"],
"category2":["image/url/3.jpg","image/url/4.jpg"]
}
I am then iterating through the object to insert the images, and all I really wanted was an elegant way to see which category was inserted first. At first I just did
for (var cat in images) {
if (i==0) firstCat = cat;
...
}
But that some how "felt" ugly... So it was basically just a question of elegance.
console.log(jsonObj[Object.keys(jsonObj)[0]]);
The order of the properties of an object are not guaranteed to be the same as the way you put them in. In practice, however, all major browsers do return them in order. So if you're okay with relying on this...
var firstProp;
for(var key in jsonObj) {
if(jsonObj.hasOwnProperty(key)) {
firstProp = jsonObj[key];
break;
}
}
Also note that there's a bug in Chrome regarding the ordering, in some edge cases it doesn't order it in the way they were provided. As far as it changing in the future, the chances are actually pretty small as I believe this is becoming part of the standard so if anything support for this will only become official.
All things considered, though, if you really, really, absolutely, positively, want to be sure it's going to be in the right order you need to use an array. Otherwise, the above is fine.
Related question: Elements order - for (… in …) loop in javascript
There isn't a "first" property. The properties of an object are unordered.
You can get whatever one the JS engine decides to provide first with a loop.
function maybe_first_in_object(ob) {
for (var props in ob) {
return prop;
}
}
… but if the order matters, use an array not an object.
Great question. I don't know of any way besides iterating in a for-in loop. You only need to iterate once though. For safety, ensure it's a known property [more info].
for (var propName in jsonObj) {
if (jsonObj.hasOwnProperty(propName)) {
return propName; // or do something with it and break
}
}
Edited to be extra clear that you're iterating over the property names, not their values.
When using jQuery, you can also use $.each to iterate over a JSON object. Looks cleaner IMO than using a for-loop
var items = {
'item1': 'content',
'item2': 'content',
'item3': 'content'
}
$.each(items, function() {
console.log($(this)[0])
})