How to access arrays with HTTP Get call in nodejs - javascript

How to get access to arrays data by requesting HTTP GET call with headers in
nodeJS. I am getting undefined error when I am trying to call the 3rd party
services. I make HTTP GET call with two headers.
This is response from HTTP GET call.
Here How I can access to "description".
{
"dotdList": [
{
"title": "From ₹ 10,299",
"description": "Haier 181 Single Door",
"url": "https://dl.flipkart.com/dl/home-kitchen/home-appliances/refrigerators/pr?sid=j9e,abm,hzg&offer=nb:mp:07de369c12&affid=fstlistgm",
"imageUrls": [
{
"url": "https://rukminim1.flixcart.com/image/800/800/j2z1fgw0/refrigerator-new/m/j/c/hrd-1813bms-r-3-haier-original-imaeu7gzwfskmxfx.jpeg?q=90",
"resolutionType": "default"
},
{
"url": "https://rukminim1.flixcart.com/image/200/200/j2z1fgw0/refrigerator-new/m/j/c/hrd-1813bms-r-3-haier-original-imaeu7gzwfskmxfx.jpeg?q=90",
"resolutionType": "low"
},
{
"url": "https://rukminim1.flixcart.com/image/400/400/j2z1fgw0/refrigerator-new/m/j/c/hrd-1813bms-r-3-haier-original-imaeu7gzwfskmxfx.jpeg?q=90",
"resolutionType": "mid"
},
{
"url": "https://rukminim1.flixcart.com/image/800/800/j2z1fgw0/refrigerator-new/m/j/c/hrd-1813bms-r-3-haier-original-imaeu7gzwfskmxfx.jpeg?q=90",
"resolutionType": "high"
}
],
"availability": "LIVE"
}
]
}
How to access to description.
Here is my actual code
var request = require('request');
request({
url: 'https://affiliate-api.flipkart.net/affiliate/offers/v1/dotd/json',
method: 'GET',
headers: {
'Fk-Affiliate-Id':'XXXXX',
'Fk-Affiliate-Id': 'XXXXXXXXXXX'
}
}, function(error, response, body) {
if(!error && response.statusCode == 200) {
let dataFs = JSON.parse(body);
let titleN = `${dataFs["dotdList"][0]["title"]}`;
console.log("error in fun");
sendTextMessage(sender, titleN);
}else {
console.error(response.error);
console.log("else error");
}
});
Part 2.This is another Response JSON
How Can I access objects from array. here I am making HTTP GET call to another url to get JSON data. below is the reponse data.
Where I am not able to access to array of data. I need to access offer_name
[
{
"featured": "0",
"exclusive": "0",
"promo_id": "P74192",
"offer_id": "180",
"offer_name": "Dominos.co.in CPS - India",
"coupon_title": "Garlic Bread & Dip free",
"category": "Food & Beverage",
"coupon_description": "TnC: Valid on Saturday",
"coupon_type": "Coupon",
"coupon_code": "NET09",
"ref_id": "src=vcommission&utm_source=Vcommission&utm_medium=Affiliate&utm_term=paid&utm_campaign=OLOHome",
"link": "http://tracking.vcommission.com/aff_c?offer_id=180&aff_id=36792",
"coupon_expiry": "2017-08-12",
"added": "2017-08-01",
"preview_url": "https://pizzaonline.dominos.co.in/",
"store_link": "http://tracking.vcommission.com/aff_c?offer_id=180&aff_id=36792",
"store_image": "http://media.vcommission.com/brand/files/vcm/180/dominos.jpg"
}
]

Answering your questions
Part 1
You already access the data's title via dataFs["dotdList"][0]["title"], and you can access the description the same way: dataFs["dotdList"][0]["description"].
Part 2
This one is quite similar to your old one. You should be able to access the fields you want via responseData[0]["offer_name"].
Explanation of Response objects, arrays, etc.
In your responses you get an array object, which you can tell by having values surrounded by brackets ([ /* data */ ]). To access values within an array, you use the access operator, like so: arrayValue[0], where 0 is the key or index of the object you are trying to fetch.
In both of your questions you are trying to access the first (and only) object within the array, and thus you can short cut that by using the 0 index of the array, i.e. responseData[0].
Within those arrays, though, you have objects. JSON Objects specifically (as is given to you by the HTTP GET request) can have fields with values which can be a string ("string"), number (0), or a boolean values (true or false). You can access the fields of an object by either accessing them using the dot operator (object.field) or by using the access operator, but with specific key (object["field"]). Using the access operator is especially useful if your field's key uses a space or number.
Putting those things together we can figure out your questions quite easily:
dataFS is an object, and we are wanting to access the elements underneath the objects in the array called "dotdList". Thus, we can access the list via the access operator (dataFs["dotdList"]), then access the first (and only) object via using the 0 index (dataFs["dotdList"][0]), and lastly accessing the fields we want by either using the dot or the access operator (dataFs["dotdList"][0]["description"] or `dataFs["dotdList"][0].description). If you need to do this multiple times, it is recommended to store the object in a variable, i.e:
var dotd = dataFs["dotdList"][0];
console.log(dotd.description) // got description!
The second part is also quite easy to figure out; you get back an array, you want the first object, and then you want to access the field: thus, access the first object using the 0 index (responseData[0]) and then access the fields you want (responseData[0].offer_name).
Always check to make sure what you are trying to access is there (i.e.the array itself in #1 and the objects within the array in both). If it isn't, your code will start throwing errors!

Related

User.findOne is looping over in object destructuring string key

I am going with an online course, there's a part where the instructor says he is trying to find/ validate a user using User.findOne and passes some conditions to find the requested user. To pass the value, he uses object destructuring. Heres the specific code:
const token = req.header("Authorization").replace("Bearer ", "");
const decoded = jwt.verify(token, "secret key here!");
// issue is here, look at the second property of the findOne function's argument.
const user=await User.findOne({_id: decoded._id, 'tokens.token': token})
The instructor is using a string key in 'tokens.token'. He's saying that, mongodb will loop over the all the tokens available in specified user object to check if the given token matches.
And if you are wondering, here's an example of a single user which contains auth tokens:
{
"name": "Prottay",
"_id": "5e27f23b6b549b4c28b8ac35",
"password": "$2a$08$gUfMwk6TNWViHihrcxjKg.8EXD04lLkGIWXqzrf8wYokdLQXHxpdy",
"tokens": [
{
"_id": "5e27f23b6b549b4c28b8ac36",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ZTI3ZjIzYjZiNTQ5YjRjMjhiOGFjMzUiLCJpYXQiOjE1Nzk2NzYyMTl9.-PWXzlEoPlEZn9F_awtzqrXOtByxUCW9RCdchHF1yKE"
},
{
"_id": "5e280429596e742dcc2f9e30",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ZTI3ZjIzYjZiNTQ5YjRjMjhiOGFjMzUiLCJpYXQiOjE1Nzk2ODA4MDl9.7W-QZ55Cc3NFd_-NPyJ0VW_5F1UVrDWAV4xHX63D6tc"
},
{
"_id": "5e280435596e742dcc2f9e31",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ZTI3ZjIzYjZiNTQ5YjRjMjhiOGFjMzUiLCJpYXQiOjE1Nzk2ODA4MjF9.vppisFiNNC_DYHtGK0IURzEOCCC5zcWl1v9yD6l1D4I"
}
],
"__v": 3
},
To me it looks like by using 'tokens.token': token instructor is trying to loop over on the user's tokens array to match the correct token.
Am I right? If I am how can he be using loop in object destructuring?
The instructor is not looping over an array using object destructuring but using the mongodb syntax for searching for a document within an array where you do not know the index before hand.
If you do not know the index position of the document nested in the array, concatenate the name of the array field, with a dot (.) and the name of the field in the nested document.
https://docs.mongodb.com/manual/tutorial/query-array-of-documents/#specify-a-query-condition-on-a-field-embedded-in-an-array-of-documents

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;
});

mochaJS: iterating in json

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) ;
}
}

Is it possible to add multiple javascript objects with the same key to an associative array?

I am working on a Javascript web application (SPA) with RESTful api on the back-end. In my client-side datacontext I want to add objects to my model graph and then send the whole graph to server at once.
Suppose the following example:
I have a Person object in my model which itself has an array of say PhoneNumbers as a property. Now I load a Person from api for edditing and map it to my model. Suppose I want to add some phone number objects to my PhoneNumbers. For this I add each number e.g. {"id": 0, "number": 6536652226} with an id of zero to my client model and send the whole graph to server when user clicks save. In server I add the objects with the id of zero (new objects) to database with auto-incremented ids.
I am doing my project based on a tutorial. They do something like this to add objects to context:
var items = {},
// returns the model item produced by merging json obj into context
mapJsonToContext = function (json) {
var id = mapper.getJsonId(json);
var existingItem = items[id];
items[id] = mapper.fromDto(json, existingItem); //returns the mapped obj
return items[id];
},
add = function (newObj) {
items[newObj.id()] = newObj;
}
The problem is that if I use this method I wouldn't be able to remove by id the newly-added-not-yet-saved items in client-side 'cause all the ids are zero!
Any suggestions to fix this, or do I need a totally different approach?
First of all, two little misconceptions I've spot:
1) Forget about "associative arrays". Numeric arrays are the only kind arrays you have; the other constructs are just "objects" (this is not PHP).
2) If it's JSON it's a string, not an object.
Other than that, you can of course use an arbitrary value to represent "new" (though I'd probably use null rather than 0) as soon as you don't use such value to uniquely identify the yet-to-add item. E.g., this is just fine:
[
{"id": 0, "number": "6536652226"},
{"id": 0, "number": "9876543210"},
{"id": 0, "number": "0123456789"}
]
This is not:
// WRONG!!!!
{
0: "6536652226",
0: "9876543210",
0: "0123456789"
}
}
And of course you cannot find numbers by ID if they still don't have an ID. You need to choose:
Retrieve the generated ID from DB and update your local data
Delete by number
Create a localId property on newly created client-side objects, and use that as your key when reconciling server returned-data. Obviously the server would have to return this localId to you.

Querying/Searching for Values within JSON

For a web site I'm creating, I have to create a quote based on data provided as a JSON string from the server. I've been looking through this site (and various others) but still am unsure on the best way to query/search the data.
For example, I need to get the Area Name from the Area ID. I need to get the maximum age for an area and also the price for a given minimum/maximum age.
I also want to get an array of prices.
Is it best to create a Javascript object from the string using the eval method? Or should I be using jQuery.
Thanks for your help.
({"SkiPass":[{"Id":1,"Area":"Chamonix","Rates":[{"Id":1,"AgeMin":0,"AgeMax":2,"Price":2.5},{"Id":2,"AgeMin":3,"AgeMax":17,"Price":5.0},{"Id":3,"AgeMin":18,"AgeMax":30,"Price":6.2},{"Id":4,"AgeMin":31,"AgeMax":59,"Price":7.4}]},
{"Id":2,"Area":"Megeve","Rates":[{"Id":1,"AgeMin":0,"AgeMax":2,"Price":1},{"Id":2,"AgeMin":3,"AgeMax":17,"Price":2.0},{"Id":3,"AgeMin":18,"AgeMax":30,"Price":2.2},{"Id":4,"AgeMin":31,"AgeMax":59,"Price":4.4}]},
{"Id":3,"Area":"Verbier","Rates":[{"Id":1,"AgeMin":0,"AgeMax":2,"Price":1.5},{"Id":2,"AgeMin":3,"AgeMax":17,"Price":3.0},{"Id":3,"AgeMin":18,"AgeMax":30,"Price":4.2},{"Id":4,"AgeMin":31,"AgeMax":59,"Price":5.4}]}]})
Create a JavaScript object from the string, most definitely, but do it with legitimate JSON parsing facilities and not "eval()". You could use jQuery, but there are other solutions, such as the JSON tools available from json.org, which are small and simple.
Once it's a JavaScript object, well then your needs should guide you as to whether some query solution is necessary, or instead that it's just a simple matter of programming.
I think the best method is jLinq: http://hugoware.net/Projects/jLinq it's like doing a SQL query on JSON.
It doesn't needs jQuery.
I use it, and it's great.
Create the object from the JSON string using JSON.parse() or jQuery.parseJSON() if you are already using jQuery -- or just pass it as from the server side as JSON.
You can then iterate through the object to find the record you want. Or, you can use build your objects so that you can naturally grab data from them.
FloatLeft - as Dan points out, your task would be much easier if you could use XPath but there is no need to re-write your data in XML format. With DefiantJS (http://defiantjs.com) you can now query JSON structure with XPath expressions.
DefiantJS extends the global object JSON with the method "search", which enables XPath queries and returns an array with the matches (empty array if no matches were found). The returned array is equipped with aggregate functions as well; one of these "sortDesc".
Check out this working fiddle;
http://jsfiddle.net/hbi99/H3PR3/
var data = {
"SkiPass": [
...
{
"Id": 3,
"Area": "Verbier",
"Rates": [
{ "Id": 1, "AgeMin": 0, "AgeMax": 2, "Price": 1.5 },
{ "Id": 2, "AgeMin": 3, "AgeMax": 17, "Price": 3 },
{ "Id": 3, "AgeMin": 18, "AgeMax": 30, "Price": 4.2 },
{ "Id": 4, "AgeMin": 31, "AgeMax": 59, "Price": 5.4 }
]
}
]
},
res1 = JSON.search( data, '//SkiPass[Id=3]/Area' ),
res2 = JSON.search( data, '//*[Area and Id=3]/Rates' )
.sortDesc('AgeMax'); // <-- sorting descending by the value of "AgeMax"
document.getElementById('name').innerHTML = res1;
document.getElementById('max_age').innerHTML = res2[0].AgeMax;
document.getElementById('price').innerHTML = res2[0].Price;

Categories