I am developing a web application in javascript (both on the server and client side). I am sending back and forth data as json, and I want to be able to parse it on the other side. The problem is that I have several levels of nested objects inside, so this is where I am stuck. For example, I am sending the following data:
var data = {};
data.title = "My Title";
data.metric = {
fact : "Malicious code detected",
technique : "XSS"
};
data.subject = {
userType : "ADMIN",
userName : "Jack",
clientNumber : "000",
terminal : "192.168.1.1"
};
data.context = {
environment : {
session : "00",
hostname : "mainServer",
sysType : "production"
},
resource : {
wpt : "DIA",
pid : "1024"
}
};
On the other side, when I receive it, I just want to be able to completely loop through this object, and print its contents. I have seen a lot of similar questions on stackoverflow, but none of them have been helpful. Here is what I have done so far:
function display(data) {
var resp = "";
var prop = null;
var dataJSON = JSON.parse(data);
for (prop in dataJSON) {
if (patternJSON.hasOwnProperty(prop)) {
resp += "obj" + "." + prop + " = " + dataJSON[prop] + "\n";
}
}
return resp;
}
But I do not know how to make it automatically go deeper, no matter the number of levels.
Can somebody point me to the right direction please?
Any help would be greatly appreciated! 10x
Define a print function
function print(obj, prefix) {
prefix = prefix || 'obj';
return Object.keys(obj).reduce(function(acc, key){
var value = obj[key];
if(typeof value === 'object') {
acc.push.apply(acc, print(value, prefix + '.' + key));
}
else {
acc.push(prefix + '.' + key + ' = ' + value);
}
return acc;
}, []);
}
And use it like this print(data).join('\n').
"obj.title = My Title
obj.metric.fact = Malicious code detected
obj.metric.technique = XSS
obj.subject.userType = ADMIN
obj.subject.userName = Jack
obj.subject.clientNumber = 000
obj.subject.terminal = 192.168.1.1
obj.context.environment.session = 00
obj.context.environment.hostname = mainServer
obj.context.environment.sysType = production
obj.context.resource.wpt = DIA
obj.context.resource.pid = 1024"
Related
I'm trying to run a procedure which queries documents and adjusts some properties according to some rules which are decided by the parameters that I pass to the query.
function downsample(ageInDays, downsampleFactor) {
var collection = getContext().getCollection();
var responseBody = {
deleted: 0,
message: ""
};
var downsampledDocuments = [];
var count = 0;
collection.queryDocuments(
collection.getSelfLink(),
'SELECT * FROM root r ' +
'WHERE (DATEDIFF(day, r.EventProcessedUtcTime, GETDATE()) > ' + ageInDays+ 'AND r.downsamplingFactor < ' + downsampleFactor + ')' +
'OR' +
'((DATEDIFF(day, r.EventProcessedUtcTime, GETDATE()) > ' + ageInDays + ' AND r.downsamplingFactor = null )' +
'ORDER BY r.did, r.resourceType ASC',
function (err, documents, options) {
if (err) throw err;
// Check the feed and if empty, set the body to 'no docs found',
// else perform the downsampling
if (!documents || !documents.length) {
var response = getContext().getResponse();
responseBody.message = "No documents found";
response.setBody(responseBody);
} else {
// We need to take into consideration that in a lot of cases, the data will already be downsampled so we
// example: previous downsampling factor of documents: 4, if a new downsampling is performed on these docs with factor 8 then we need to
var adjustedDownSamplingFactor;
if (documents[0].downsamplingFactor == null) {
adjustedDownSamplingFactor = downsampleFactor;
} else {
adjustedDownSamplingFactor = downsampleFactor / documents[0].downsamplingFactor;
}
var aggregatedDocument = documents[0];
var documentValueSum = 0;
var documentCount = 0;
var aggregatedDocumentValue = 0;
for(doc in documents){
if(!aggregatedDocument){
aggregatedDocument = doc;
}
if(documentCount >= adjustedDownSamplingFactor || aggregatedDocument.did !== doc.did || aggregatedDocument.resourceType !== doc.resourceType){
// preparing aggregated document
aggregatedDocumentValue = documentValueSum / documentCount;
aggregatedDocument.value = aggregatedDocumentValue;
aggregatedDocument.downsamplingFactor = downsampleFactor;
//Adding the downsampled data to the Array which will be uploaded to the cosmosdb
downsampledDocuments.push(aggregatedDocument);
aggregatedDocument = null;
documentCount = 0;
documentValueSum = 0;
continue;
}
documentValueSum += doc.value;
documentCount++;
}
var response = getContext().getResponse();
tryDelete(documents);
// Call the CRUD API to create a document.
tryCreate(downsampledDocuments[count], callback);
responseBody.message = "Downsampling was succesful"
response.setBody(responseBody);
}
});
So I'm not passing any documents to the query so I don't know which partition key I would have to supply to the stored procedure. Is there any way in which I can avoid having to supply a partition key? I'm calling this stored procedure from an API but keep getting a message that I should supply a partition key.
Is there any way in which I can avoid having to supply a partition
key?
Unfortunately no. You have to supply a partition key value.
I am making a website using YouTube API and i need to get users channel id to retrieve there data
How can i do this in JavaScript
Thanks in advance 😊
this code is working already in my project.
can you try this code,
Maybe solve your problem with this code.
youtubeChannelId = channelName => {
if (channelName) {
var name = getChannelFromUrl(channelName);
var url =
'https://gdata.youtube.com/feeds/api/users/' +
name +
'?fields=id&alt=json';
var result = UrlFetchApp.fetch(url);
var data = Utilities.jsonParse(result.getContentText());
if (
typeof data['entry'] !== 'undefined' &&
data['entry']['id']['$t'] !== 'undefined'
) {
var id = 'UC' + data['entry']['id']['$t'].split('/').pop();
return id;
}
}
return '';
};
getChannelFromUrl = url => {
var pattern = new RegExp(
'^(https?://)?(www.)?youtube.com/(user/)?([a-z-_0-9]+)/?([?#]?.*)',
'i',
);
var matches = url.match(pattern);
if (matches) {
return matches[4];
}
return url;
};
I am having an issue getting the javascript script for the executeScript nifi process to work and would appreciate help with this. The goal is to pass a flowfile which will contain a json object. I need to parse this json without knowing the content/fields prior and pass this along to write it out to the flowfile that is being passed out to the next process that is MergeContent and counts the number flowfiles.
Tried testing the script and got the following error:
nifi.script.ExecuteScript - ExecuteScript[id=bd6842e9-e3a4-4d88-a59d-
7da1d74d109b] ExecuteScript[id=bd6842e9-e3a4-4d88-a59d-7da1d74d109b]
failed to process due to
org.apache.nifi.processor.exception.ProcessException:
javax.script.ScriptException: <eval>:21:17 Expected : but found value
let value = json[key];
^ in <eval> at line number 21 at column number 17; rolling
back session: org.apache.nifi.processor.exception.ProcessException:
javax.script.ScriptException: <eval>:21:17 Expected : but found value
I am not very familiar with javascript so would appreciate the help.
flowFile = session.get();
if (flowFile != null) {
var StreamCallback =
Java.type("org.apache.nifi.processor.io.StreamCallback");
var IOUtils = Java.type("org.apache.commons.io.IOUtils");
var StandardCharsets = Java.type("java.nio.charset.StandardCharsets");
var transformed_message = {};
var error = false;
var line = "ops_testQueue";
flowFile = session.write(flowFile, new StreamCallback(function
(inputStream, outputStream) {
var content = IOUtils.toString(inputStream,
StandardCharsets.UTF_8); // message or content
var message_content = {};
try {
message_content = JSON.parse(content);
if(Array.isArray(message_content)){
}
Object.keys(message_content).forEach((key) => {
var value = json[key];
result.push(key + '=' + value);
var jkey = "," + "\"" + key + "\"" + '=' + value
});
line = line + jkey +
" value=" + "1"
+ " " + Date.now() * 1000000;
// Write output content
if (transformed_message) {
outputStream.write(line.getBytes(StandardCharsets.UTF_8));
}
} catch (e) {
error = true;
outputStream.write(content.getBytes(StandardCharsets.UTF_8));
}
}));
if (transformed_message.post_state) {
flowFile = session.putAttribute(flowFile, "type",
transformed_message.type);
}
if (error) {
session.transfer(flowFile, REL_FAILURE)
} else {
session.transfer(flowFile, REL_SUCCESS)
}
}
EDIT:
input to executeScript:
{"pID":"1029409411108724738",
"contentType":"text",
"published":"2018-08-14 16:48:23Z",
"crawled":"2018-08-14 12:48:33-04:00",
"ID":"765"}
output from executeScript:
ops_testQueue,"ID"=765 value=1 1534265314969999870
Am I missing something?
I saw a couple of things here:
I don't know if Nashorn (Java's JS Engine) supports the full lambda
syntax, I was able to get it to work by making the lambda a function
(see script below).
You refer to a json variable to get the value from a key, but I think you want message_content.
result is not defined, so you get an error when you push to it.
Here's an edited version of your script that I got to work the way I think you want it (but please correct me if I'm wrong):
flowFile = session.get();
if (flowFile != null) {
var StreamCallback =
Java.type("org.apache.nifi.processor.io.StreamCallback");
var IOUtils = Java.type("org.apache.commons.io.IOUtils");
var StandardCharsets = Java.type("java.nio.charset.StandardCharsets");
var transformed_message = {};
var error = false;
var line = "ops_testQueue";
flowFile = session.write(flowFile, new StreamCallback(function
(inputStream, outputStream) {
var content = IOUtils.toString(inputStream,
StandardCharsets.UTF_8); // message or content
var message_content = {};
try {
message_content = JSON.parse(content);
if(Array.isArray(message_content)){
}
var jkey = "";
Object.keys(message_content).forEach(function(key) {
var value = message_content[key];
//result.push(key + '=' + value);
jkey = "," + "\"" + key + "\"" + '=' + value
});
line = line + jkey +
" value=" + "1"
+ " " + Date.now() * 1000000;
// Write output content
if (transformed_message) {
outputStream.write(line.getBytes(StandardCharsets.UTF_8));
}
} catch (e) {
error = true;
log.error(e);
outputStream.write(content.getBytes(StandardCharsets.UTF_8));
}
}));
if (transformed_message.post_state) {
flowFile = session.putAttribute(flowFile, "type",
transformed_message.type);
}
if (error) {
session.transfer(flowFile, REL_FAILURE)
} else {
session.transfer(flowFile, REL_SUCCESS)
}
}
Ok, this one has to be a very easy question, but I just started learning node. I am also new to javascript, so, please show no mercy on pointing out wrong directions below.
In particular I have two files:
one has a class that creates some slave servers in different ports
the other one is the "main" file that generates the slaves
When I attempt to print out what I have just initialized I get two weird errors:
connections property is deprecated. Use getConnections() method, and then
it crashes when I attempt to apply JSON.stringify in the new object (Converting circular structure to JSON)
Code for slaves in file "slave.js":
var http = require ("http");
function Slave () {
}
Slave.prototype.ID = undefined;
Slave.prototype.coordinator = false;
Slave.prototype.httpServer = undefined;
Slave.prototype.thePort = undefined;
Slave.prototype.isCoordinator = function () { return this.coordinator; }
/*****************************************************************/
function handle_incoming_request (req, res) {
console.log("INCOMING REQUEST: " + req.method + " " + req.url);
res.writeHead (200, { "Content-Type" : "application/json" });
res.end( JSON.stringify({ "error" : null }) + "\n" );
}
exports.createSlave = function (id, coordinatorK, port) {
var temp = new Slave ();
temp.ID = id;
temp.coordinator = coordinatorK;
temp.thePort = port;
temp.httpServer = http.createServer(handle_incoming_request);
temp.httpServer.listen (temp.thePort);
console.log ("Slave (" + (temp.isCoordinator() ? "coordinator" : "regular") + ") with ID " + temp.ID + " is listening to port " + temp.thePort);
console.log ("--------------------------------------------");
return temp;
}
Now, the main file.
var http = require ("http");
var url = require ("url");
var a = require ("./slave.js");
var i, temp;
var myArray = new Array ();
for (i = 0; i < 4; i++) {
var newID = i + 1;
var newPort = 8000 + i + 1;
var coordinatorIndicator = false;
if ((i % 4) == 0) {
coordinatorIndicator = true; // Say, this is going to be a coordinator
}
temp = a.createSlave (newID, coordinatorIndicator, newPort);
console.log ("New slave is : " + temp);
console.log ("Stringified is: " + JSON.stringify(temp));
myArray.push(temp);
}
You're trying to stringify the result of http.createServer(...). That'll not be what you want to do, so when you create that property, make it non-enumerable by defining it using Object.defineProperty().
exports.createSlave = function (id, coordinatorK, port) {
var temp = new Slave ();
temp.ID = id;
temp.coordinator = coordinatorK;
temp.thePort = port;
Object.defineProperty(temp, "httpServer", {
value: http.createServer(handle_incoming_request),
enumerable: false, // this is actually the default, so you could remove it
configurable: true,
writeable: true
});
temp.httpServer.listen (temp.thePort);
return temp;
}
This way JSON.stringify won't reach that property curing its enumeration of the object.
Issue is the with the property httpServer of temp object having circular reference. You can either set it non enumerable using Ecmascript5 property definision as mentioned in the previous answer or you can use the replacer function of JSON.stringify to customize it not to stringify the httpServer property.
console.log ("Stringified is: " + JSON.stringify(temp, function(key, value){
if(key === 'httpServer') return undefined;
return value;
}));
I'm trying to build a database based on some arbitrary data on a website. It's complex and changes for each site so I'll spare the details. Here's basically what I'm trying to do
function level0(arg) { textarea.innerHTML += arg + ' = {'; }
function level1(arg) { textarea.innerHTML += '\n\t' + arg + ': ['; }
function level2(arg) { textarea.innerHTML += arg + ', '; }
And so on. The thing is some level1's don't have any children and I can't get the formatting right.
My three problems are as follows.
The ending commas are going to break in IE (thank you MS)
Empty level1's shouldn't be printed if they don't have any children
Closing /curly?brackets/
HERE'S A DEMO of what I have so far. Notice the ending commas, the empty sub2 which shouldn't be printed, and no closing brackets or braces
Do I need to redesign the entire thing?
Is there also a way to have this all in one function so I don't have to worry if I add another layer?
EDIT
This needs to be done in a string format, I can't build an object and then stringify it, mostly because I need to know which element I'm in the middle of adding to.
Overall it looks that you still might want to build an object, but in case you insist on not building it - here is some sample solution:
function Printer() {
var result = '',
lastLevel = null,
close = {0:'\n}', 1:']', 2:''},
delimiter = {0: ',\n', 1:',\n', 2:','};
function closeLevel(level, noDelimiter) {
if(lastLevel === null)
return;
var l = lastLevel, d = level == lastLevel;
while(l >= level) {
result += close[l] + (l == level && !noDelimiter ? delimiter[l]:'');
l--;
}
}
this.level0 = function(arg) {
closeLevel(0);
result += arg + ' = {\n';
lastLevel = 0;
};
this.level1 = function(arg) {
closeLevel(1);
result += '\t' + arg + ': [';
lastLevel = 1;
};
this.level2 = function(arg) {
closeLevel(2);
result += arg;
lastLevel = 2;
};
this.getResult = function() {
closeLevel(lastLevel, true);
return result;
}
}
var p = new Printer();
p.level0('head');
p.level1('sub1');
p.level2('item1');p.level2('item2');p.level2('item3');
p.level1('sub2');
p.level1('sub3');
p.level2('newthing');
p.level0('head2');
document.getElementById('textarea').value = p.getResult();
You could see it in action here.
I'm not sure why you're building what looks like objects with nested arrays, using string concatenation. Something like this would be much simpler, since it wouldn't require fixing trailing commas, etc:
Edit: I've updated the code to make it keep track of the last level put in.
function Db() {
var level0, level1;
var data = new Object();
this.level0 = function(arg) {
level0 = new Object();
data[arg] = level0;
}
this.level1 = function(arg) {
level1 = new Array();
level0[arg] = level1;
}
this.level2 = function(arg) {
level1.push(arg);
}
this.toString = function() {
var s = '';
for(i in data) {
s += i + '\n';
for(j in data[i]) {
if(data[i][j].length>0) {
s += '\t' + j + ': [' + data[i][j] + ']\n' ;
}
}
}
return s;
}
}
Use like this:
var db = new Db();
db.level0('head');
db.level1('sub1');
db.level2('item1');db.level2('item2');db.level2('item3');
I've tested this in the demo you linked and it works just fine.