Process two nearly identical JSON blocks with one set of code

23
January 01, 2019, at 02:10 AM

My goal is to send JSON returned from an API request to Slack. My code works when I send JSON of one content type. However, I need to accomplish this for two content types. I would like to efficiently parse the JSON for the two content types and use a single block of code to send the JSON to Slack. Examples below illustrate.

JSON block 1 - Content

{
    "Content": {
        "CreatedByUser": {
            "DisplayName": "<username>",
            "ProfileUrl": "<profileurl>"
        },
        "HtmlName": "<name>",
        "HtmlDescription": "<html>",
        "Url": "<url>"
    }
}

JSON block 2 - Comment

Note that JSON block 1 is nested:

{
    "Comment": {
        "Content": {
            "CreatedByUser": {
                "DisplayName": "<username>",
                "ProfileUrl": "<profileurl>"
            },
            "HtmlName": "<name>",
            "HtmlDescription": "<html>",
            "Url": "<url>"
        }
    }
}

JS code that parses and perform actions

This shows my current code that deals only with JSON block 1.

The values are extracted:

var request = require('request');
function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
        var info = JSON.parse(body);
        var username = info.Content.CreatedByUser.Username;
        var profileUrl = info.Content.CreatedByUser.ProfileUrl;
        var subject = info.Content.HtmlName;
        var url = info.Content.Url
        var text = info.Content.HtmlDescription;
    };

All values are sent to Slack:

    function sendToSlack(theUsername, theIconEmoji) {
        var payload = {
            attachments: [{
                author_name: username,
                author_link: profileUrl,
                title: subject,
                title_link: url,
                text: text
            }]
        };
        var theRequest = {
            url: urlWebHook,
            method: "POST",
            json: payload
        };
        request(theRequest, function (error, response, body) { });
    }
    var urlWebHook = "<webhook url>";
    sendToSlack();

Rather, I would like the code to process both JSON blocks 1 and 2 without duplicating code. For example, I believe I can do something like:

if (info.hasOwnProperty('Content')) {
    var username = info.Content.CreatedByUser.Username;
    var profileUrl = info.Content.CreatedByUser.ProfileUrl;
    var subject = info.Content.HtmlName;
    var url = info.Content.Url
    var text = info.Content.HtmlDescription;
};
if (info.Comment.hasOwnProperty('Content')) {
    var username = info.Comment.CreatedByUser.Username;
    var profileUrl = info.Content.CreatedByUser.ProfileUrl;
    var subject = info.Comment.HtmlName;
    var url = info.Comment.Url
    var text = info.Comment.Body;
};

...followed by the code to send the JSON to Slack.

(I know the above is inaccurate -- I am just trying to communicate my thinking.)

But, if I understand correctly and based on experimentation, that would require me to duplicate the "send to Slack" code inside each if clause because, if the variables are outside an if clause, they are not otherwise recognized as defined. Instead, I would like to use the "send to Slack" code one time only for simpler maintenance and cleaner code.

I am new to JavaScript. I am stuck at this point and would be grateful for any guidance.

Answer 1

As Pointy commented, variables declared with var are treated as if they were declared at the very top of the containing function. This is as opposed to variables declared with let in ES6. So your code as-is should actually work. You may want to define the variables without setting them before the if, as some people don't like declaring vars in an if block:

var username, profileUrl, subject, url, text;
if (info.hasOwnProperty('Content')) {
    username = info.Content.CreatedByUser.Username;
    profileUrl = info.Content.CreatedByUser.ProfileUrl;
    subject = info.Content.HtmlName;
    url = info.Content.Url
    text = info.Content.HtmlDescription;
};
if (info.hasOwnProperty('Comment')) {
    username = info.Comment.CreatedByUser.Username;
    profileUrl = info.Content.CreatedByUser.ProfileUrl;
    subject = info.Comment.HtmlName;
    url = info.Comment.Url
    text = info.Comment.Body;
};

To make it more efficient, you can extract the values only once by changing what variable they are pulling from:

var content;
if (info.hasOwnProperty('Content')) {
    content = info.Content;
}
if (info.hasOwnProperty('Comment')) {
    content = info.Comment.Content;
}
var username = content.CreatedByUser.Username;
var profileUrl = content.CreatedByUser.ProfileUrl;
var subject = content.HtmlName;
var url = content.Url
var text = content.HtmlDescription;
READ ALSO
When using Select2, field gets too narrow when there are no options

When using Select2, field gets too narrow when there are no options

When there are no options, the select box shrinks to too narrow width & even "No results found" appears distorted

33
How to download tickers from webpage, beautifulsoup didnt get all content

How to download tickers from webpage, beautifulsoup didnt get all content

I want to get the ticker values from this webpage https://wwwoslobors

21
how to pass id from a form in html using nodejs mysql

how to pass id from a form in html using nodejs mysql

Here is the html form through this I can input the client id through the dropdown and I want to use that client id which come from the dropdown to pass through the form:

41
Get Child item from xml document

Get Child item from xml document

I have the following XML document and i am trying to find a way to be able to pass a host name and then get the following host-ip entry for that hostname

29