mochaJS: iterating in json - javascript

i have following issue, i have part of json returned by api:
...
"name": "NEWS",
"products": {
"10432471": {
"id": 10432471,
"productConfig": [
...
]
},
"10432481": {
"id": 10432481
},
"17300241": {
"id": 17300241
},
"17300251": {
"id": 17300251,
"productConfig": [
...
]
},
"18420501": {
"id": 18420501
}
}
...
and i want to get random simple product id (simple product means that it dont have productConfig field inside)
for (i=0;i<res.body.menu.categories.length;i++){
if(res.body.menu.categories[i].name=='NEWS'){
availableProducts = Object.keys(res.body.menu.categories[i].products);
console.log ('avbl prods from news category: ',availableProducts);
for (j=0;;j++){
random=Math.floor(Math.random()*Object.keys(res.body.menu.categories[i].products).length);
if(assert.notInclude(res.body.menu.categories[i].products[random],'productConfig')){
availableProductIdForDelivery = res.body.menu.categories[i].products[random].id;
break;
}
}
}
}
This code gives me error in line with second if (if(assert.notInclude....)) Uncaught AssertionError: object tested must be an array, a map, an object, a set, a string, or a weakset, but undefined given.
So, inside "products" we dont have array, becouse there're {}, not []?
There's any other way to iterate beetween products (their numerical names are changed everyday) and save id to availableProductIdForDelivery

Take a look at the documentation: http://www.chaijs.com/api/assert/#method_notinclude
You see that the first parameter must be Array, String or haystack. Let's take a look at the error message you have given:
Uncaught AssertionError: object tested must be an array, a map, an
object, a set, a string, or a weakset, but undefined given.
This error message indicates that something was undefined instead of the possible expected types listed in the message. I guess it was the first parameter, but it might be the third as well, since you did not pass anything as the third parameter, so it is undefined.

So, inside "products" we dont have array, becouse there're {}, not []?
Correct. As far as I can tell, you are trying to apply an assertion to res.body.menu.categories[i].products[random], but because products is an object (and not a list) attempting to retrieve an index (as oppose to one of the keys defined in the object) with products[random] returns undefined.
If you want to create a list of products in order to evaluate their contents, you may be able to use Object.values(res.body.menu.categories[i].products)[random]. As far as I am aware, this feature is only standard as of ES2017. You may also be able to apply a map function to your availableProducts object to retrieve the corresponding values for each product key.

Ok, thanks for help, now its works as i want. Below my solution, maybe it help someone in the future:
for (i=0;i<res.body.menu.categories.length;i++){
if(res.body.menu.categories[i].name=='NEWS'){ //random simple product from 'news' category
availableProducts = Object.keys(res.body.menu.categories[i].products);
console.log ('avbl prods from news category: ',availableProducts);
while(availableProductIdForDelivery==''){
random=Math.floor(Math.random()*Object.keys(res.body.menu.categories[i].products).length);
if((Object.values(res.body.menu.categories[i].products)[random].productConfig).length==0)
availableProductIdForDelivery = Object.values(res.body.menu.categories[i].products)[random].id;
}
console.log('random simple product: '+availableProductIdForDelivery) ;
}
}

Related

Zapier - Catch Hook - JSON Array - Loop over each item in array

I need to use a Zapier webhook to take some incoming JSON data, which contains an array of items, loop that array and do an action for each element.
Here's a sample of incoming JSON data:
{
"first_name": "Bryan",
"last_name": "Helmig",
"age": 27,
"data": [
{
"title": "Two Down, One to Go",
"type": "Left"
},
{
"title": "Talk the Talk",
"type": "Right"
},
{
"title": "Know the Ropes",
"type": "Top"
}
]
}
The size of the array will be dynamic.
The problem is that when I import this data in the hook, it gives me
data
title: Two Down, One to Go
type: Left
title: Talk the Talk
type: Right
title: Know the Ropes
type: Top
So, basically it says that data is just a big string of all this stuff together.
Can anyone help me figure out if it's possible to have a Zap loop over this and do something, e.g., insert data into a sheet, for ever item in the array? I'm aware of the "Code" actions, I've chosen JavaScript, which I could parse out the string, but that doesn't seem efficient. Plus, in reality, there will be a lot of data in the objects inside the JSON array.
EDIT: SOLVED! ANSWER BELOW
So, the first part is to Catch Raw Hook for a trigger. It's the normal "Webhooks", but you have to click to show the less common variations. With the Catch Raw Hook, your data will not be turned automatically turned into variables via the Zapier app, you'll have the raw JSON data.
Once you have the raw JSON, in my case, you'll have an action, and this will be the "Code" action. I'm using JavaScript. In my template, I'm grabbing the entire JSON string (your whole imported JSON is a string right now, not an object, so we can't use "." (dot) notation to access parts of it).
You'll need to JSON.parse() the string in the code. But first, let me explain that Zapier has a pre-defined variable called inputData that you'll use in your code. Then in the top of the "Edit Template" section of your "Code" Action, you'll see you can name the variable of that JSON string you imported.
Now the fun part! In the code, you'll type:
// of course, you can change the variables to what you want
// but 'inputData' is unique, can't change that
const myData = JSON.parse(inputData.rawJsonData);
So, my raw data is a string, it's not JSON yet, so this line of code makes it a JSON object. And now, as an object we can loop over it or .map or access 'this.that' or whatever you want.
The next important thing to mention about "Code" in Zapier, is that to get your stuff out, you return. So, in the next few lines, I'm going to return a .map function that returns each item in an array. And it's tough to grasp how Zapier treats this, but it actually runs the next "Action" you create (e.g. adding a row to a sheet) for each time you loop in that .map. So, let's take a look below:
return myData.data.map(item => {
return item;
});
If you remember, I had an array called "data" in my raw JSON I listed in the original question. It will loop over that array and since I'm returning, then it will perform an "Add Row to Sheet" (in my case) for each loop, thus, inserting all of my data as multiple rows in my spreadsheet.
So the finished code:
const myData = JSON.parse(inputData.rawJsonData);
return myData.data.map(item => {
return item;
});

Index on array keypath doesn't find any values

I want to get familiar with indexedDB to built my Firefox WebExtension.
My sample data is structured like this:
const sampleDataRaw = [
{
"ent_seq" : 1413190,
"att1" : [ {
"sub11" : "content1",
"sub12" : [ "word" ]
}, {
"sub11" : "content2"
} ],
"att2" : [ {
"sub21" : "other content",
"sub22" : [ "term" ]
} ]
}, {
"ent_seq" : 1000010,
"att2" : [ {
"sub21" : "more content"
}, {
"sub22" : "more words"
} ]
}
] // end sampleRawData
I got as far as opening/creating my database, adding this sample data and querying it by the ent_seq key using objectStore.get() and objectStore.openCursor().
The problem arises when I want to search the sub11 or sub21 fields using indexes I should have created for these like this:
objectStore.createIndex("sub11Elements", "att1.sub11", { unique: false });
objectStore.createIndex("sub21Elements", "att2.sub21", { unique: false });
When I want to search, say, fields sub11 as here:
var index = objectStore.index("sub11Elements");
index.get("content1").onsuccess = function(event) {
// I should have the first object of my data now, alas the result is undefined instead
};
It certainly does succeed, but the returned value is undefined since the get() didn't actually find anything.
I want to know why it doesn't find the entry and how to make it find it. I figured it might be because the keypath is wrong, but as stated, if I instead search by the key (ent_seq) I can successfully get the result.att1[i].sub11 values.
On mozilla's websites it's stated that keys can be of type string and array (or array within array etc) amongst others, and keypath parts are supposed to be concatenated using dots.
From searching on stackexchange I've so far found that it's not possible to have variable keys inside the keypath, but that shouldn't be the case here anyway.
Therefore, I really don't see what might be causing the search to not find the object inside the database.
It looks like the second level of objects are arrays, not properties of the first level of objects. The . accessor accesses sub properties, not indices of an array.
IDBObjectStore.prototype.get always yields success when there is no error, and is not indicative of whether a match was found.
A bit more on point 1. Look at "att1":[{"sub11" : "content1","sub12" : [ "word" ]}.... Pretend this was was an actual basic JavaScript object. Would you be able to use att1.sub11? No. Because the value of att1 is an array, not an object.

Issue retrieving JSON data in javascript

I have a Json schema like this:
{"THEMES":{
"CATEGORY":
["TEST1","TEST2","TEST3","DFSDFSDF"],
"OVER AGAIN":
["YOUNG","OLD","GRANPA"],
"AND AGAIN":
["AND","ANOTHER","WORD"],
"NEW CATEGORY":
["AGAIN","OOPS","CAN","REDBULL"]
}}
Well, I need to retrieve the keys values inside an AngularJs Controller and my code to retrieve it is like:
$http.get('json/word_bank.json')
.success(function (result) {
$scope.themes = Object.keys(result.TEMAS);
console.log($scope.themes);
And I get in my console:
["CATEGORY", "OVER AGAIN", "AND AGAIN", "NEW CATEGORY"]
So far so good, but I need to access the keys values like TEST1, TEST2, etc.
For this i've tried, for example:
console.log($scope.themes[0][0]);
And the console return the letter "C" or the first letter of the "CATEGORY" string. And this is happening with all of the rest, so the code is transforming my initial array into string elements, I guess. I already tried a lot of loops or iterations over the array, but I not works. Am I missing something?
$scope.themes Is referring to an array of the object keys in the result.THEMES object. When you call $scope.themes[0][0], you are getting the first item of the keys array "CATEGORY", and then the first character of that string "C".
You will need a reference to the actual themes object, then pass the name of the theme to get its values.
themesObject[$scope.themes[0]] -> ["TEST1","TEST2","TEST3","DFSDFSDF"]
Using your code:
$http.get('json/word_bank.json')
.success(function(result) {
$scope.themes = Object.keys(result.THEMES);
console.log(result.THEMES[$scope.themes[0]]);
});

How to get a sort order from wildcard property name

My JSON object looks like this and I want to sort them based on property starting with sort_
{
"sort_11832": "1",
"productsId": [
"11832",
"160",
"180"
],
"sort_160": "0",
"sort_180": "2"
}
Ideally I would like to get a result of ids based on sort order like this -
[ "160","18832","180" ]
Any suggestion on how to sort by wildcard property name. Using Javascript/Jquery ofcourse.
Here's what I'd do:
Go back to whatever is producing that truly absurd data and have them just return an array in the correct order in the first place, rather than producing an array and then repeating all the entries as separate properties with sort_ in front of them and a number.
Very, very, very, very far down in second place if the above weren't successful, I'd do this:
Call sort on the array, passing in a comparator function
In the comparator function, put "sort_" in front of each of the two values the function was given to compare, and use that property name to look up the the numeric string for that property in the object
Parse those two numeric strings into numbers
Return the result of subtracting the second one's number from the first
Code is left as an exercise to the reader.
Thanks everyone. It was a daft way of approaching this. Point taken and I have now changed the data set to something like this which makes everything very easier -
sort: [
{
\"id\": \"160\",
\"sort\": 0
},
{
\"id\": \"11832\",
\"sort\": 1
}
]

The comments I am retrieving when using the Instagram API are returning 'undefined'

I'm retrieving data from
https://api.instagram.com/v1/tags/HASHTAG/media/recent?client_id=CLIENT_ID
whereHASHTAG = the hashtag I'm searchingCLIENT_ID = my client idI am having no trouble retrieving the picture urls and captions but when I try to get the comments the comments are being returned as 'undefined'.The data is stored in an array called pictures so if I want to get the standard resolution url I just do:
for(i = 0; i < pictures.length; i++){
pictureURL[i] = pictures[i].images.standard_resolution.url;
}
Right now the code I'm trying to use to retrieve the comments is :
//where 'i' is the index of the pic I'm currently focusing on
for (comment in pictures[i].comments.data) {
alert(comment.text);
//using alert just to see what is being retrieved
}
But the issue is that the alerts are only displaying 'undefined' and also they are only displaying undefined when there is a comment (I checked on my phone, if the pic has no comment, there is no alert. If the picture has comments there is 1 alert for each comment.Can someone please help me out?
The value in pictures[i].comments.data is an array, as shown in the "Response" section in the /tags/tag-name/media/recent Instagram API docs:
[{
"type": "image",
...
"comments": {
"data": [{
"created_time": "1296703540",
"text": "Snow",
...
},
{
"created_time": "1296707889",
"text": "#snow",
...
}],
...
As you can see, the data property in the comments object is an array (beginning with [).
You're misusing for..in on an array. (See Why is using "for...in" with array iteration a bad idea?) for..in loops over property names of objects. The value of comment will always be a property name string, which certainly has no text property.
Instead, you need a plain for loop, because pictures[i].comments.data is an array:
for (var j=0; j<pictures[i].comments.data.length; j++) {
var comment = pictures[i].comments.data[j];
alert(comment.text)
}
One important note is that even if pictures[i].comments.data had been a non-array object, your use of for..in still wouldn't be quite right. Your variable comment holds property names, and you need to use property-access to get the value that a property name refers to:
for (commentKey in pictures[i].comments.data) {
var commentValue = pictures[i].comments.data[commentKey];
alert(commentValue.text)
}
Note that this might work for arrays, but:
The property names may not loop in numerical order
This will loop over all iterable properies of the array, not just numeric indices

Categories