Trouble parsing JSON with Google Scripts - json

I'm using Google Apps Scripts to parse some JSON and it's not working...
Here's my pseudo-code:
function fetchInsta() {
var url = "xxx";
Logger.log(url);
var result = UrlFetchApp.fetch(url);
var json = JSON.parse(result.getContentText());
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var existingids = sheet.getRange("D:D");
for(i in json.data){
for(j in existingids){
if(json.data[i].id = existingids[i]){
var match = true;
}
}
if(match != true){
var id = json.data[i].id;
var image = json.data[i].images.standard_resolution.url;
var username = json.data[i].user.username;
var link = json.data[i].link;
var date = json.data[i].createdtime;
sheet.appendRow([image,username,link,id,date]);
Logger.log([image,username,link,id,date]);
}
}
}
I've removed the URL as it has my API key in it. But here's a sample of the JSON returned:
"data":[
{
"attribution":null,
"tags":[ ],
"type":"image",
"location":{ },
"comments":{ },
"filter":"Normal",
"created_time":"1430751422",
"link":"https:\/\/instagram.com\/p\/2Q6AiIG4hT\/",
"likes":{ },
"images":{ },
"users_in_photo":[ ],
"caption":{ },
"user_has_liked":false,
"id":"977536242480285779_10266761",
"user":{ }
},
I'm getting the variables image, username, link fine - but id and date are both undefined. Any ideas what's happening? What am I doing wrong?

This line of code:
if(json.data[i].id = existingids[i]){
Is using an assignment operator to test for equality. Equality tests are done with double or triple equal signs. If in doubt, use triple equal signs.
Should be:
if(json.data[i].id === existingids[i]){

Related

How to get unique data of google sheets to json with appscript?

I'm getting values of the sheet in JSON format. My Sheet
I've added this code in appscript to get JSON:
var ss = SpreadsheetApp.openByUrl("Spreadsheet URL");
var sheet = ss.getSheetByName('Sheet1');
function doGet(e){
var action = e.parameter.action;
if(action == 'getItems'){
return getItems(e);
}
}
function getItems(e){
var records={};
var rows = sheet.getRange(2, 1, sheet.getLastRow() - 1,sheet.getLastColumn()).getValues();
data = [];
for (var r = 0, l = rows.length; r < l; r++) {
var row = rows[r],
record = {};
record['customerName'] = row[0];
record['docketNo']=row[1];
record['docketDate']=row[2];
record['destination']=row[3];
record['weight']=row[4];
data.push(record);
}
records = data;
var result=JSON.stringify(records);
return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);
}
Current JSON data:
[
{
"customerName":"cash",
"docketNo":"d87976489",
"docketDate":"2021-08-14T18:30:00.000Z",
"destination":"kanpur",
"weight":1
},
{
"customerName":"cash",
"docketNo":"d87976480",
"docketDate":"2021-08-12T18:30:00.000Z",
"destination":"kanpur",
"weight":1
},
{
"customerName":"abc",
"docketNo":"d87976482",
"docketDate":"2021-09-12T18:30:00.000Z",
"destination":"mumbai",
"weight":2
}
]
I want this JSON data:
[
{
"customerName":"cash",
"docketNo":"d87976489","d87976480",
"docketDate":"2021-08-14T18:30:00.000Z","2021-08-12T18:30:00.000Z",
"destination":"kanpur","kanpur",
"weight":1,1
},
{
"customerName":"abc",
"docketNo":"d87976482",
"docketDate":"2021-09-12T18:30:00.000Z",
"destination":"mumbai",
"weight":2
}
]
I have the same customer names therefore, I want unique data. I've searched many websites & videos but I didn't get one.
Please give me appscript code to get this data!
You can do it with some Javascript acrobatics
Sample:
function makeJsonUnique() {
var json = [
{
"customerName":"cash",
"docketNo":"d87976489",
"docketDate":"2021-08-14T18:30:00.000Z",
"destination":"kanpur",
"weight":1
},
{
"customerName":"cash",
"docketNo":"d87976480",
"docketDate":"2021-08-12T18:30:00.000Z",
"destination":"kanpur",
"weight":1
},
{
"customerName":"abc",
"docketNo":"d87976482",
"docketDate":"2021-09-12T18:30:00.000Z",
"destination":"mumbai",
"weight":2
}
]
var customerNames = json.map(e=>e.customerName)
var uniqueCustomerNames = [...new Set(customerNames)]
var newJSON =[]
uniqueCustomerNames.forEach(function(name){
var tempObj ={}
tempObj.customerName = name
var jsonSubsets = json.filter(function(obj){return obj.customerName == name})
tempObj.docketNo = jsonSubsets.map(obj=>obj.docketNo).join(",")
tempObj.docketDate = jsonSubsets.map(obj=>obj.docketDate).join(",")
tempObj.destination = jsonSubsets.map(obj=>obj.destination).join(",")
tempObj.weight = jsonSubsets.map(obj=>obj.weight).join(",")
console.log(JSON.stringify(tempObj))
newJSON.push(tempObj)
})
console.log(newJSON)
}
Used methods:
map()
filter()
...newSet()
push()
join()

JSON to Google sheet --> Strange Columns + Everything in one cell

So far i managed to get a connection to a secure JSON. What i dont get to work is the data nice in columns. Plus in the metadata there a nice "labels" but now i get weird column names. Date: Streetname for example.
I have tried a couple of questions on this site. but i dont get it to work.
This is my JSON data (sorry it is in dutch)(so as you can see Project: Zipcode....?):
{
"skip": 0,
"take": 100,
"rows": [
{
"Volgnummer": 1,
"Omschrijving": "Projectnaam",
"Omschrijving_2": "Productnaam",
"Trailercodering": "productnaam-01",
"Omschrijving_3": "Warehouse",
"Datum_laden": "3 juni 2019",
"Tijdstip_laden": "1600 - 1800",
"Datum_aankomst_lossen": "4 juni 2019",
"Tijdstip_lossen": "0800 - 1000",
"Naam": "Transporteur",
"Datum": "Straat"
"Herkomst": huisnummer,
"Navigatie_transport": null,
"Project": "6644 KX",
"Woonplaats": "Ewijk",
"Land": "Nederland"
},
And this is my Google-Script code so far:
function pullJSON1() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheet = ss.getActiveSheet();
var url= "https://the-url.com");
var headers = {
"Authorization": "AfasToken "+
Utilities.base64Encode(<token><version>1</version><data> hier de
token</data></token>)
};
var options = {
"method" : "get",
"headers" : headers
};
var response = UrlFetchApp.fetch(url,options); // get feed
var dataAll = JSON.parse(response.getContentText());
var rows = [Object.keys(dataAll)]; // Retrieve headers.
var temp = [];
for (var i = 0; i < rows[0].length; i++) {
temp.push(dataAll[rows[0][i]]); // Retrieve values.
}
rows.push(temp);
sheet.getRange(1,1,rows.length,rows[0].length).setValues(rows);
// Put values to Spreadsheet.
}
sheet output
(source: imggmi.com)
Can someone help?
I would this rearranged in columns. Also my output in the sheet gives me 1 entry but there a 356 enterys in total.
Great thanks,
Remco
Do you need the "skip", "take" variables? These don't fit with the tabular data, plus they seem to be part of a pagination system (in which case you should probably hide it from the results). Below I provide code to put the actual rows into your sheet:
function pullJSON1() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheet = ss.getActiveSheet();
var url = "https://the-url.com";
var headers = {
"Authorization": "AfasToken " + Utilities.base64Encode("<token><version>1</version><data> hier de token</data></token>");
};
var options = {
"method" : "get",
"headers" : headers
};
var response = UrlFetchApp.fetch(url, options); // get feed
var dataAll = JSON.parse(response.getContentText());
var dataRows = dataAll['rows'];
var rowHeaders = Object.keys(dataRows[0]);
var rows = [rowHeaders]; // Retrieve headers.
for (var i = 0; i < dataRows.length; i++) {
var rowData = [];
for (var j = 0; j < rowHeaders.length; j++) {
rowData.push(dataRows[i][rowHeaders[j]]); // Retrieve values.
}
rows.push(rowData);
}
sheet.getRange(1,1,rows.length,rows[0].length).setValues(rows);
// Put values to Spreadsheet.
}

How do i get a JSON file out of my SpreadSheet

I want to get a JSON out my spreadsheet that looks like this() and to extract a JSON file like this:
[{ "module": "ModuleA",
"Questions" : [{
"Question": "xxxx",
"Answers" : ["1","2","3"],
"right answer" : "2",
}
]
This is what i have by now but its not in the coreect hierarchy
function doGet(){
var ss = SpreadsheetApp.openById('14-vl75N4mAv9FdZNHIhX_lhtQ-XY17lOvEnLIjiSwDc');
var result={};
var sheetA = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheetA')
.getDataRange()
.getValues();
var sheetB = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheetB')
.getDataRange()
.getValues();
result.sheetA = makeObject(sheetA);
result.sheetB = makeObject(sheetB);
Logger.log(result.sheetA)
//return ContentService.createTextOutput(JSON. stringify(result))
//.setMimeType(ContentService.MimeType.JSON);
}
function makeObject(multiArr) {
var obj = {};
var headers = multiArr.shift()
for(var i = 0; i< headers.length; i++){
obj[headers[i]]= multiArr.map(function(app){
return app[i];
});
}
return obj;
}
What about this solution?
function doGet(){
var ss = SpreadsheetApp.openById('14-vl75N4mAv9FdZNHIhX_lhtQ-XY17lOvEnLIjiSwDc');
var result={};
var sheetA = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheetA')
.getDataRange()
.getValues();
var sheetB = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheetB')
.getDataRange()
.getValues();
result.sheetA = makeObject(sheetA);
result.sheetB = makeObject(sheetB);
Logger.log(makeObject(sheetA))
}
function makeObject(multiArr) {
var obj = [];
for(var i=1;i<multiArr.length;i++)
{
obj.push( {
"Question": multiArr[i][1],
"Answers" : [multiArr[i][2],multiArr[i][3],multiArr[i][4]],
"right answer" : multiArr[i][5],
}
)
}
var myJSON=[{ "module": multiArr[1][0],
"Questions" : obj
}]
return JSON.stringify(myJSON);
}
You can push into an array your data formatted according to the hierarchy of
your choice, populate it within a loop with the contents of each row
in your sheet and then JSON.stringify it.
This works as above provided you have only one module per sheet. Otherwise, you need to implement an additional function which would detect in which row ModuleA ends and ModuleB starts.

Trying to fetch JSON data and put it to googlesheet

I have problem with value setting in googlesheet. Googlesheet setValue support only array but i need to put object in rows.
I tried use appendRow but it won't work in custom functions. I also tried setValue with converting my objects to array but then i missed some data.
This is my fetching function. It works and gets all data i need but it's really hard for me to place it into googlesheet.
function importTrelloJSON(url){
var response = UrlFetchApp.fetch(url);
var content = response.getContentText();
var data = JSON.parse(content);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var trelloJSON = data.map(function(el, index) {
var customFieldItems = el.customFieldItems.map(function(el){
return [el.idCustomField, el.value.number];
});
return { name: el.name, customFieldItems: customFieldItems };
});
retrun trelloJSON;
}
and this is my JSON structure, sometimes there is nested data
[
{
"id": "5ce26ef1d5bdac4ec20e8982",
"name": "WWW",
"customFieldItems": []
},
{
"id": "5ced04d96ec7ed6120b5e91d",
"name": "Marketing",
"customFieldItems": []
},
{
"id": "5cfed3d8e88f931008aa58ad",
"name": "Reset softu Android",
"customFieldItems": [
{
"id": "5cfed4145d019516555a9086",
"value": {
"number": "100"
},
"idCustomField": "5ced79c27bbd7102945ba1ff",
"idModel": "5cfed3d8e88f931008aa58ad",
"modelType": "card"
}
]
},
I tried using ready importJSON function https://github.com/bradjasper/ImportJSON but it's not working with my queries.
Thanks for help.
//edit
Now i can display data but when i push to array i have problem with range. The number of data columns does not match the number of columns in the range.
I tried Math.max.apply(Math, trelloJSON.map(function (el) { return el.length })). But it's not working anymore.
Here is my new code:
function importTrelloJSON(url){
var response = UrlFetchApp.fetch(url);
var content = response.getContentText();
var data = JSON.parse(content);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var mainArray = new Array();
var trelloJSON = data.map(function(el, index) {
mainArray = [];
mainArray.push(el.name);
el.customFieldItems.map(function(el){
mainArray.push(el.idCustomField);
mainArray.push(el.value.number);
});
Logger.log(mainArray);
return mainArray;
});
sheet.getRange(1,1, trelloJSON.length, Math.max.apply(Math, trelloJSON.map(function (el) { return el.length }))).setValues(trelloJSON);
}

Instagram JSON TypeError: Cannot read property "text" from undefined

I'm trying to build analytics with Google Sheet for Instagram, but I keep getting errors when I want to return the caption text from an image url.
I've tried different variations of my code, but it's always the same issue. Either my result comes back (in the output) as "undefined", or it just throws errors.
function MultipleHashtags() {
//Set up multiple sheets and instagram accounts
var hashtagArray = ["fitness", "fashion"];
for(var i = 0; i < hashtagArray.length; i++) { grabData( hashtagArray[i]); };
//Grab data from TOP 9 posts
function grabData(tag) {
var url = "https://www.instagram.com/explore/tags/"+tag+"/?__a=1";
var response = UrlFetchApp.fetch(url).getContentText();
for(var i = 0; i < 9; i++) {
var hashtag = JSON.parse(response).graphql.hashtag.name;
var postOwner = JSON.parse(response).graphql.hashtag.edge_hashtag_to_top_posts.edges[i].node.owner.id;
var shortCode = JSON.parse(response).graphql.hashtag.edge_hashtag_to_top_posts.edges[i].node.shortcode;
var URL = "https://www.instagram.com/p/"+shortCode;
var isVideo = JSON.parse(response).graphql.hashtag.edge_hashtag_to_top_posts.edges[i].node.is_video;
var PostComments = JSON.parse(response).graphql.hashtag.edge_hashtag_to_top_posts.edges[i].node.edge_media_to_comment.count;
var PostLikes = JSON.parse(response).graphql.hashtag.edge_hashtag_to_top_posts.edges[i].node.edge_liked_by.count;
var caption = JSON.parse(response).graphql.hashtag.edge_hashtag_to_top_posts.edges[i].node.edge_media_to_caption.edges.node.text;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet2");
sheet.appendRow([Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd"), hashtag, postOwner, shortCode, URL, isVideo, PostComments, PostLikes, caption])
var range = sheet.getRange("A2:H")
range.sort([{column: 1, ascending: false}]);
Utilities.sleep(200);;
}
}
};
Might not be the best code yet, but i'm still learning :). Any help would be appreciated.
What this script does is read the dump that's behind this URL:
https://www.instagram.com/explore/tags/fashion/?__a=1
for instance:
"graphql":{"hashtag":{"name":"fashion","is_top_media_only":false,"profile_pic_url":"https://scontent-bru2-1.cdninstagram.com/vp/3919f4813f1759cd589c9e256fafa05b/5B584579/t51.2885-15/s150x150/e35/c0.135.1080.1080/29717343_617997658538341_2606017788199829504_n.jpg","edge_hashtag_to_media":{"count":494984995,"page_info":{"has_next_page":true,"end_cursor":"AQBYZqz6Bc4vBlwhzRuhZm1NQSk7HQmHsJ9ZdMzanB-4UAH9rfDCjuWq-iqx5iEEaT0pPeJ_2aydWn_ZToa_aR5wt2ww743GTMbvIfx1lEAlpQ"},"edges":[{"node":{"comments_disabled":false,"id":"1750034539685082052","edge_media_to_caption":{"edges":[{"node":{"text":"NEW | Our new webshop is online!\n\nwww.ivan-online.nl\nFrom now on you can order your shawl easily online. A special gift for yourself, or for someone else. A warm shawl with a warm story.\n\nLet us know what you think about it \ud83d\ude4f \u2014\n\u2014\n#webshop #fashion #shawl #sjaal #cashmere #kasjmir #internetfashion #fashionable #handmade #nepal #fairtrade #springfashion #2018\n#photo"}}]},"shortcode":"BhJXyRKl_PE","edge_media_to_comment":{"count":0},"taken_at_timestamp":1522840395,"dimensions":{"height":720,"width":1080},"display_url":"https://scontent-bru2-1.cdninstagram.com/vp/cbf53cb645805430051bc7b056fb1dbf/5B643AD8/t51.2885-15/e35/29414609_430637507388196_1941728523811028992_n.jpg","edge_liked_by":{"count":0},"edge_media_preview_like":{"count":0},"owner":{"id":"5998662494"},"thumbnail_src":"https://scontent-bru2-1.cdninstagram.com/vp/68d5e9377dee9bfb0165bfa18473b6c6/5B56C8D8/t51.2885-15/s640x640/sh0.08/e35/c180.0.720.720/29414609_430637507388196_1941728523811028992_n.jpg","thumbnail_resources":[{"src":"https://scontent-bru2-1.cdninstagram.com/vp/e8a4b97569e409822c382ddb3231af00/5B62B69B/t51.2885-15/s150x150/e35/c180.0.720.720/29414609_430637507388196_1941728523811028992_n.jpg","config_width":150,"config_height":150},{"src":"https://scontent-bru2-1.cdninstagram.com/vp/fbc573c382379e29a4b321b1b5e423c3/5B5A190D/t51.2885-15/s240x240/e35/c180.0.720.720/29414609_430637507388196_1941728523811028992_n.jpg","config_width":240,"config_height":240},{"src":"https://scontent-bru2-1.cdninstagram.com/vp/a5b50f4711a8ab1774320c912cb70b7c/5B620CE5/t51.2885-15/s320x320/e35/c180.0.720.720/29414609_430637507388196_1941728523811028992_n.jpg","config_width":320,"config_height":320},{"src":"https://scontent-bru2-1.cdninstagram.com/vp/b27613e12796dfb97803acd4e429c20d/5B5C9FCC/t51.2885-15/s480x480/e35/c180.0.720.720/29414609_430637507388196_1941728523811028992_n.jpg","config_width":480,"config_height":480},{"src":"https://scontent-bru2-1.cdninstagram.com/vp/68d5e9377dee9bfb0165bfa18473b6c6/5B56C8D8/t51.2885-15/s640x640/sh0.08/e35/c180.0.720.720/29414609_430637507388196_1941728523811028992_n.jpg","config_width":640,"config_height":640}],"is_video":false}}
In there is the following line that's of interest:
"edge_media_to_caption":{"edges":[{"node":{"text":"NEW | Our new webshop is online!\n\nwww.ivan-online.nl\nFrom now on you can order your shawl easily online. A special gift for yourself, or for someone else. A warm shawl with a warm story.\n\nLet us know what you think about it \ud83d\ude4f \u2014\n\u2014\n#webshop #fashion #shawl #sjaal #cashmere #kasjmir #internetfashion #fashionable #handmade #nepal #fairtrade #springfashion #2018\n#photo"}}]}
Which i'm trying to grab with:
var caption = JSON.parse(response).graphql.hashtag.edge_hashtag_to_top_posts.edges[i].node.edge_media_to_caption.edges.node.text;
And this returns the error:
TypeError: Cannot read property "text" from undefined
From stackdriver:
2018-04-04 14:20:42.316 CEST
TypeError: Cannot read property "text" from undefined. at grabData(GrabData:21) at MultipleHashtags(GrabData:5)
Expand all | Collapse all {
insertId: "198nrphg1tmmbn6"
jsonPayload: {…}
labels: {…}
logName: "projects/project-id-1872200188033847311/logs/script.googleapis.com%2Fconsole_logs"
receiveTimestamp: "2018-04-04T12:20:43.328274499Z"
resource: {…}
severity: "ERROR"
timestamp: "2018-04-04T12:20:42.316Z"
}
The reason you're getting the errors is because you're trying to access an object property that doesn't exist. Unfortunately, this is heavily nested data, so you'll need to do a lot of checks here. There are multiple ways to do this, but I used this as a guide.
In the code below, I broke out your grabData() function as I'm personally not a fan of nested functions.
function MultipleHashtags() {
//Set up multiple sheets and instagram accounts
var hashtagArray = ["fitness", "fashion"];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet2");
var range = sheet.getRange("A2:H")
range.sort([{column: 1, ascending: false}]);
Utilities.sleep(200);;
for(var i = 0; i < hashtagArray.length; i++) {
var data = grabData(hashtagArray[i]);
sheet.appendRow([Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd"), data.hashtag, data.postOwner, data.shortCode, data.URL, data.isVideo, data.PostComments, data.PostLikes, data.caption]);
}
}
//Grab data from TOP 9 posts
function grabData(tag) {
var url = "https://www.instagram.com/explore/tags/"+tag+"/?__a=1";
var response = UrlFetchApp.fetch(url).getContentText();
var responseObject = JSON.parse(response);
var hashtagData = responseObject.graphql.hashtag;
var data = {};
for(var i = 0; i < 9; i++) {
var hashtag = hashtagData.name;
if (checkNested(hashtagData, "edge_hashtag_to_top_posts", "edges")) {
var edge = hashtagData.edge_hashtag_to_top_posts.edges[i];
if (checkNested(edge, "node")) {
var node = edge.node;
var postOwner = checkNested(node, "owner", "id") ? node.owner.id : "";
var shortCode = checkNested(node, "shortcode") ? node.shortcode : "";
var URL = "https://www.instagram.com/p/"+shortCode;
var isVideo = checkNested(node, "is_video") ? node.is_video : "";
var PostComments = checkNested(node, "edge_media_to_comment", "count") ? node.edge_media_to_comment.count : "";
var PostLikes = checkNested(node, "edge_liked_by", "count") ? node.edge_liked_by.count : "";
var caption = "";
if (checkNested(node, "edge_media_to_caption", "edges")) {
var captions = node.edge_media_to_caption.edges[0];
caption = checkNested(captions, "node", "text") ? captions.node.text : "";
}
}
}
data = {
"hashtag": hashtag,
"postOwner": postOwner,
"shortCode": shortCode,
"URL": URL,
"isVideo": isVideo,
"PostComments": PostComments,
"PostLikes": PostLikes,
"caption": caption
};
}
return data;
}
/**
* Test for existence of nested JavaScript object key
* Copied from https://stackoverflow.com/questions/2631001/test-for-existence-of-nested-javascript-object-key
*/
function checkNested(obj /*, level1, level2, ... levelN*/) {
var args = Array.prototype.slice.call(arguments, 1);
for (var i = 0; i < args.length; i++) {
if (!obj || !obj.hasOwnProperty(args[i])) {
return false;
}
obj = obj[args[i]];
}
return true;
}
EDIT: Forgot a major point about your original code. When you were accessing the caption, var caption = JSON.parse(response).graphql.hashtag.edge_hashtag_to_top_posts.edges[i].node.edge_media_to_caption.edges.node.text;, the last edges is actually an array. In my code, I only selected the first element of that array. You can update as necessary.