I am trying to render a jade with some dynamic content. I am reading from a json in jade.
My json looks like this
{ data1: 'data1',
data2: 'data2',
data3:
[ { name: 'ABC',
address: 'India'
},
{ name: 'DEF',
address: 'Australia'
}]}
I am trying to render a jade and use the data from above json
my jade looks like
var data1 = #{data1};
var data2 = #{data2};
var size = #{data3.length};
for data in #{data3}
var name = data.name;
var address = data.address;
I am able to correctly extract data in the first 3 lines mentioned above. But when I try to fetch data from within a loop, I get "Uncaught SyntaXError, Unexpected Identifier" error while debugging.
If i put a line outisde the for loop, it works fine. Ex
var name = #{data3[0].name};
is rendered properly. But i need to iterate over a loop and fetch data over there. Can somebody help.
Thanks
Updating with more information
1. I have node server running where I create a json -
var json_string = "{"data1":"data1","data2":"data2","data3":[{"name":"ABC","address":"India"},{"name":"DEF","address":"Australia"}]};";
var json_data = JSON.parse(json_string);
console.log(json_data);
res.render('sample_example', json_data);
In my sample_example.jade I have the following snippet within script
var data1 = #{data1};
var data2 = #{data2};
var size = #{data3.length};
for data in #{data3}
var name = data.name;
var address = data.address;
As stated earlier, I am able to properly extract #{data1}, #{data2}, #{data3.length} to the variables . But it breaks within the for loop. In fact, I am able to extract #{data3[0].name} from outside the for loop. But within the for looop it gives the stated error.
This is how you can do it now.
In your server-side you have to JSON.stringify the array of objects.
var json_data = JSON.parse(json_string);
// Convert back to json only the property data3
json_data.data3 = JSON.stringify(json_data.data3);
res.render('simple', json_data);
Or the better is to not parse the JSON just let it go the way it is:
// var json_data = JSON.parse(json_string);
res.render('simple', {
json_data: json_string
});
And in the Jade Template (If you followed the better method):
script(type='text/javascript').
var json_data = !{json_data};
var data1 = json_data.data1;
var data2 = json_data.data2;
var data3 = json_data.data3;
var size = data3.length;
data3.forEach(function(data) {
var name = data.name;
var address = data.address;
console.log(name, address);
});
Also you need to change the loop structure. The for..in used to iterate over objects not array of objects.
This works for me;
- var cdata = {"data1":"data1","data2":"data2","data3":[{"name":"ABC","address":"India"},{"name":"DEF","address":"Australia"}]};
each data in cdata.data3
- var name = data.name;
- var address = data.address;
p Name: #{name}
p Address: #{address}
Can you share the actual jade file contents if updating the code as shown above doesn't work. Also what version of jade and express?
Related
I'm trying to import JSON via API into Google sheets but get the error
Cannot read property 'length' of undefined
Here is my code
function importRank(){
url = 'https://public-api.solscan.io/token/holders?tokenAddress=sinjBMHhAuvywW3o87uXHswuRXb3c7TfqgAdocedtDj&offset=0&limit=max'
var json = JSON.parse(UrlFetchApp.fetch(url).getContentText())
var data = json.data.owner
var data2 = json.data.rank
var data3 = json.data.total
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('WalletRank')
sh.getRange(2,1,data.length,data[0].length).setValues(data)
sh.getRange(2,2,data2.length,data2[0].length).setValues(data2)
sh.getRange(2,3,data3.length,data3[0].length).setValues(data3)
}
Try
function importRank(){
url = 'https://public-api.solscan.io/token/holders?tokenAddress=sinjBMHhAuvywW3o87uXHswuRXb3c7TfqgAdocedtDj&offset=0&limit=max'
var json = JSON.parse(UrlFetchApp.fetch(url).getContentText())
var data=[]
Logger.log(json.total)
json.data.forEach(function(x){
data.push([x.owner,x.rank,x.amount])
})
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('WalletRank')
sh.getRange(2,1,data.length,data[0].length).setValues(data)
sh.getRange(2,4).setValue(json.total)
}
Explanation
the structure is as follows
{"data":[
{"address":"__________","amount":________,"decimals":__,"owner":"___","rank":_},
...
],"total":_____}
that means that data is an array [] of multi elements which contains each of them {} address, amount, decimals, owner and rank
Reference
forEach
I am looking for help from this community regarding the below issue.
// I am searching my Gmail inbox for a specific email
function getWeeklyEmail() {
var emailFilter = 'newer_than:7d AND label:inbox AND "Report: Launchpad filter"';
var threads = GmailApp.search(emailFilter, 0, 5);
var messages=[];
threads.forEach(function(threads)
{
messages.push(threads.getMessages()[0]);
});
return messages;
}
// Trying to parse the HTML table contained within the email
function getParsedMsg() {
var messages = getWeeklyEmail();
var msgbody = messages[0].getBody();
var doc = XmlService.parse(msgbody);
var html = doc.getRootElement();
var tables = doc.getDescendants();
var templ = HtmlService.createTemplateFromFile('Messages1');
templ.tables = [];
return templ.evaluate();
}
The debugger crashes when I try to step over the XmlService.parse function. The msgbody of the email contains both text and HTML formatted table. I am getting the following error: TypeError: Cannot read property 'getBody' of undefined (line 19, file "Code")
If I remove the getParsedMsg function and instead just display the content of the email, I get the email body along with the element tags etc in html format.
Workaround
Hi ! The issue you are experiencing is due to (as you previously mentioned) XmlService only recognising canonical XML rather than HTML. One possible workaround to solve this issue is to search in the string you are obtaining with getBody() for your desired tags.
In your case your main issue is var doc = XmlService.parse(msgbody);. To solve it you could iterate through the whole string looking for the table tags you need using Javascript search method. Here is an example piece of code retrieving an email with a single table:
function getWeeklyEmail() {
var emailFilter = 'newer_than:7d AND label:inbox AND "Report: Launchpad filter"';
var threads = GmailApp.search(emailFilter, 0, 5);
var messages=[];
threads.forEach(function(threads)
{
messages.push(threads.getMessages()[0]);
});
return messages;
}
// Trying to parse the HTML table contained within the email
function getParsedMsg() {
var messages = getWeeklyEmail();
var msgbody = messages[0].getBody();
var indexOrigin = msgbody.search('<table');
var indexEnd = msgbody.search('</table');
// Get what is in between those indexes of the string.
// I am adding 8 as it indexEnd only gets the first index of </table
// i.e the one before <
var Table = msgbody.substring(indexOrigin,indexEnd+8);
Logger.log(Table);
}
If you are looking for more than one table in your message, you can change getParsedMsg to the following:
function getParsedMsg() {
// If you are not sure about how many you would be expecting, use an approximate number
var totalTables = 2;
var messages = getWeeklyEmail();
var msgbody = messages[0].getBody();
var indexOrigin = msgbody.indexOf('<table');
var indexEnd = msgbody.indexOf('</table');
var Table = []
for(i=0;i<totalTables;i++){
// go over each stable and store their strings in elements of an array
var start = msgbody.indexOf('<table', (indexOrigin + i))
var end = msgbody.indexOf('</table', (indexEnd + i))
Table.push(msgbody.substring(start,end+8));
}
Logger.log(Table);
}
This will let you store each table in an element of an array. If you want to use these you would just need to retrieve the elements of this array and use them accordingly (for exaple to use them as HTML tables.
I hope this has helped you. Let me know if you need anything else or if you did not understood something. :)
I am importing data from a JSON file using Google Apps Script and Google Sheets. I have learned the basics on this, but the formatting on the JSON file I am attempting to parse is throwing me off.
What is confusing me is how I would search for information based on "name". Currently I am using this:
function JSONReq(url, xpath){
var res = UrlFetchApp.fetch(url);
var content = res.getContentText();
var json = JSON.parse(content);
var patharray = xpath.split("/");
for(var i = 0; i < patharray.length; i++){
json = json[patharray[i]];
}
return json;
}
I'm a bit lost now to be honest with you.
I want to have a cell where I can type a name that I already know of, then find it in the JSON file and pull the return that information however I decide to do it. I can pull and write to cells, I have the basics down. But I just can't understand how I could search by the name.
That JSON file is an array of objects. To find a specific object with a given "name", you would parse it into an object (which you do already), then iterate through them and check the name parameter:
var myName = "name of thing I want";
var arr = JSON.parse( ... );
for(var i = 0; i < arr.length; ++i) {
var obj = arr[i];
if(obj.name == myName) { // could be done as obj["name"] == ... too
// do stuff with obj
}
}
For your case, you might add an additional argument to your function (i.e. 2nd arg = the object's property, e.g. "name", with the 3rd = the desired value. This will be fine for any simple key-value properties, but would need specific handling for where the value is itself an object (e.g. the "category" field in your specific JSON file).
I have a JSON string in this format:
[
{
"Origin":{
"FtpHost":"info",
"FtpFolder":"info",
"FtpUser":"info",
"FtpPassword":"info",
"FtpInsideFolder":"info",
"Pattern":"info"
},
"Destination":{
"FtpHost":"info",
"FtpFolder":"info",
"FtpUser":"info",
"FtpPassword":"info",
"FtpInsideFolder":"info"
},
"CustomFolderName":"Conad",
"OperationTraverseType":"RootOnly"
}
]
To pick up the JSON I wrote this in Node.js:
var fs = require('fs');
var obj = fs.readFileSync('Operations.json', 'utf8');
I'm wondering, how I can access for example : "Destination" fields?
You must parse this to JSON. because fs.readFile returns string
var fs = require('fs');
var obj = fs.readFileSync('Operations.json', 'utf8');
obj = JSON.parse(obj)
var Destination = obj[0].Destination
// or
var Destination = obj[0]["Destination"]
Edit (as said Diego)
You can also directly require json file
var obj = require('somejsonfile.json');
var Destination = obj[0]. Destination
Just need to simply parse the read data. Something like this:
var fs = require('fs');
var obj = fs.readFileSync('Operations.json', 'utf8').toString();
obj = JSON.parse(obj)
console.log(obj[0].Destination)
you can do like var myjson = JSON.parse(obj) or obj = JSON.parse(fs.readFileSync('Operations.json', 'utf8')) and then access it like obj[0]["Destination"]["FIELD"] where FIELD - represents the "Destination" object field you want
I have a bunch of JSON files that I need to parse (in node), but many of the files have things like this:
"_id" : NumberLong(528000021)
Where NumberLong is a function out of scope of the JSON file. When I run JSON.parse I get an error (understandably) that it found an unexpected token. Is there a way to create a function NumberLong and inject it into the scope of the parse?
--EDIT--
Gave #Svabael the answer karma on this one, but for the curious here is how I ended up solving the problem. I created GLOBAL functions for any function appearing in the "JSON", and then created a module then required it.
#!/usr/bin/env node
var fs = require('fs');
GLOBAL.ISODate = function(x){return x};
GLOBAL.NumberLong = function(x){return x};
var source = "./JSONFiles/";
var target = "./JSONModules/";
for(var i=2;i<process.argv.length;i++) {
var fn = process.argv[i];
var sn = source + fn;
var sd = fs.readFileSync(sn,'utf8');
var tn = target + fn.replace('.json','.js');
var td = "module.exports = " + sd;
fs.writeFileSync(tn,td);
var json = require(tn);
//json now has the data
}
To call the script above it is a bash one-liner:
ls JSONFiles | xargs ./json2modules.js
This is not a valid JSON:
{
"_id" : NumberLong(528000021)
}
This is a valid JSON:
{
"_id" : "NumberLong(528000021)"
}
I think that you are trying to parse a javascript object and the error that you have is normal. If this is the case, then you don't need to parse it at all.