I have a JSON response as below;
"finalData" :
[
{
"message":"Display success msg",
"status":["SUCCESS"]
},
{
"message":"Display fail msg",
"status":["FAIL"]
}
]
Now this is dynamic. Meaning, I can either get just "SUCCESS" or just "FAILURE" or both
So finalData can be an array of 0 or 1 or 2 objects
My question is what is the best way to access the "message" property of the array dynamically. i.e. I want to know if finalData.message belongs to
"status":["SUCCESS"] or "status":["FAILURE"]
So kind of associate the array
var d = { "finalData": [{ "message": "Display success msg", "status": ["SUCCESS"] }, { "message": "Display fail msg", "status": ["FAIL"] }] }
var status = 'SUCCESS';
var message = d.finalData.filter(e => e.status == status).map(e => e.message)[0];
document.write(message);
ES5 code:
var d = { "finalData": [{ "message": "Display success msg", "status": ["SUCCESS"] }, { "message": "Display fail msg", "status": ["FAIL"] }] }
var status = 'SUCCESS';
var message = d.finalData.filter(function(e) {
return e.status == status;
}).map(function(e) {
return e.message;
})[0];
document.write(message);
Check whether each code is there, then just use an if statement to continue conditionally, depending on the status.
var status = finalData[0].status;
var succeeded = status.indexOf('SUCCESS') >= 0;
var failed = status.indexOf('FAIL') >= 0;
if(succeeded && failed) {
// code when both are true
}
else if(succeeded) {
// code for only success
}
else if(failed) {
// code for only failure
}
else {
// code if neither are present
}
Related
I am trying to build out an API endpoint within Workato using a Javascript plugin. Part of the requirement is to validate if the JSON request is valid based on the schema that I defined.
Specifically, I need to throw a 400 Bad Request error if a required field is not provided or if the provided value does not match the expected data type (e.g. string when expecting number).
My original thought was to define a "checkRequest" function that will intake the JSON request object with every possible data point and essentially run through a huge list of if/else if /else conditions to test every value for "null" and use "type of" to test for data type and then return if I encounter an error.
However, note that the schema is HUGE with about 100 different data points and consists of nested objects within objects so I was hoping to find the most optimized way to iterate rather than relying on a bulk of if statements.
See my code below and a snippet of a request based on the schema (can't share full schema):
My code:
function checkRequest({
partner_id,
merchant_reference_id,
optional_string,
}) {
let response = {
validRequest: true,
responseStatus: "",
errorTitle: "",
errorDetail: "",
errorCode: "",
};
let badRequestTitle = "Bad Request";
let requiredFieldErrorDetail = (field) => {
return field + " is a required field but was not provided in request.";
};
let wrongFormatErrorDetailDetail = (field, inputDataType, expectedDataType) =>
field +
" expected data type is " +
expectedDataType +
", but " +
inputDataType +
" was received.";
//partner_id
if (partner_id == "" || partner_id == null) {
response.validRequest = false;
response.errorDetail = requiredFieldErrorDetail("partnerID");
console.log(response);
return response;
} else if (typeof partner_id != "string") {
response.validRequest = false;
response.responseStatus = "400";
response.errorCode = "40001";
response.errorTitle = badRequestTitle;
response.errorDetail = wrongFormatErrorDetail(
"partnerID",
typeof partner_id,
"string"
);
console.log(response);
return response;
}
//merchant_reference_ID
else if (merchant_reference_id == "" || merchant_reference_id == null) {
response.validRequest = false;
response.errorDetail = requiredFieldErrorDetail("partnerID");
console.log(response);
return response;
} else if (typeof merchant_reference_id != "string") {
response.validRequest = false;
response.responseStatus = "400";
response.errorCode = "40001";
response.errorTitle = badRequestTitle;
response.errorDetail = wrongFormatErrorDetail(
"partnerID",
typeof merchant_reference_id,
"string"
);
console.log(response);
return response;
}
//else
else {
console.log(response);
return response;
}
}
let requestBody = {
partner_id: "",
merchant_reference_id: "aa",
optional_string: "3",
};
checkRequest(requestBody);
Sample request snippet (assume that some fields are required and others are optional):
{
"application": {
"partnerReferral": {
"partnerID": "mg3e09f8-a8dd-44e6-bb06-55293b799318",
"merchantReferenceID": "mg3e09f8a8dd44e6bb06-55293b799318"
},
"businessInformation": {
"identity": [
{
"identifier": "EMPLOYER_IDENTIFICATION_NUMBER",
"value": "77-1122333"
}
],
"businessType": "ASSOCIATION",
"classification": {
"code": "SIC",
"value": "string"
}
}
}
}
Hoping to rely on vanilla Javascript to accomplish this is the best way possible, but open to plugins if necessary.
I'm making a hybrid app and using WKWebView.
I need to pass a JavaScript Object to the emitter command to open the edit dialog.
Here is my code:
let statDict: [String: Any] = [
"income" : account.stat.income,
"expense" : account.stat.expense,
"summary" : account.stat.summary,
"incomeShorten" : account.stat.incomeShorten,
"expenseShorten" : account.stat.expenseShorten,
"summaryShorten": account.stat.summaryShorten
]
let accountDict: [String: Any] = [
"id": account.id,
"name": account.name,
"description": "",
"icon": account.icon,
"currency": account.currency,
"customer_contact_id": account.customer_contact_id ?? 0,
"is_archived": account.is_archived,
"sort": account.sort,
"create_datetime": account.create_datetime,
"update_datetime": account.update_datetime ?? "",
"stat": statDict
]
let accountData = try! JSONSerialization.data(withJSONObject: accountDict, options: JSONSerialization.WritingOptions(rawValue: 0))
guard let accountString = String(data: accountData, encoding: .utf8) else {
return
}
webView.evaluateJavaScript("function parse(string){ return JSON.parse(string)}") { result, error in
if error == nil { // this is returns correct staff
}
}
webView.evaluateJavaScript("parse('\(accountString)')") { object, error in
if error == nil {
let object = object as AnyObject
print("parse object \(object)")
webView.evaluateJavaScript("window.emitter.emit('openDialog', 'Account', \(object))") { (result, error) in
if error == nil { // here the error "Unexpected token '='..."
webView.evaluateJavaScript("window.emitter.on('closeDialog', function(){ window.webkit.messageHandlers.emitterMessage.postMessage('closeDialog'); })") { (result, error) in
if error == nil {
}
}
webView.evaluateJavaScript("window.emitter.on('createAccount', function(){ window.webkit.messageHandlers.emitterMessage.postMessage('createAccount'); })") { (result, error) in
if error == nil {
}
}
} else {
print(error as Any)
}
}
}
}
The \ (object) returned by the function looks like this:
{
"create_datetime" = "2021-08-24 19:19:28";
currency = RUB;
"customer_contact_id" = 1;
description = "";
icon = "";
id = 7;
"is_archived" = 0;
name = "Business 111";
sort = 0;
stat = {
expense = 0;
expenseShorten = 0;
income = 300000;
incomeShorten = 300K;
summary = 300000;
summaryShorten = 300K;
};
"update_datetime" = "";
}
but it should look like this:
{
create_datetime: "2021-08-24 19:19:28",
currency: "RUB",
customer_contact_id: 1,
description: "",
icon: "",
id: 7,
is_archived: false,
name: "Business 111",
sort: 0,
stat: {
expense: 0,
expenseShorten: "0",
income: 300000,
incomeShorten: "300K",
summary: 300000,
summaryShorten: "300K"
},
update_datetime: ""
}
With such an object, the compiler generates the error Unexpected token '='. Expected an identifier as property name.
The parse (string) function will return the correct object if you run it in the js compiler, but in swift the output is not correct.
How to bring an object to the correct form?
You are trying to pass the string interpolated representation of a Swift object (NSMutableDictionary in your case) to Javascript.
Instead you can directly pass the JSON representation to JS context since JSON is a native Javascript object it should do what you are trying to achieve :
/// Sample emitter function that consumes object an prints its local parameter, also assigns it to sample object value in window.
self.webView?.evaluateJavaScript(
"window.emitter = (sampleObject) => { window.sampleObject = sampleObject;setTimeout(function(){console.log('Hello sampleObject : ',sampleObject.name); }, 7000);}"
) { result, error in
if error == nil { // this is returns correct staff
}
}
self.webView?.evaluateJavaScript("window.emitter(\(accountString));") { result, error in
if error == nil {
print("parse object \(result)")
}
}
Result in window :
I'm trying to make a Google Hangouts Chat Bot that detects when a form has been filled in, and sends the responses of the most recent form submission to Hangouts Chat using a bot. I have built this off existing code (my JS / GAS knowledge is near zero), mainly based on the GitHub TSFormBot repo. The issue is, it is sending each response invidiually as a different message, instead of 1 single message with all of the content.
For exmaple, a 4 question form causes the bot to send 4 individual replies, with one of the different answers in each. Could you please help me see where I'm going wrong, so I could get the content of all 4 answers in a single response?
Thanks!
Current code:
function postToRoom(e) {
var formResponses = FormApp.getActiveForm().getResponses();
var formResponse = formResponses[formResponses.length-1];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
var options, options, url;
url = PropertiesService.getScriptProperties().getProperty('WEBHOOK_URL');
if (url) {
try {
payload = {
"cards": [
{
"header": {
"title": "There is a new request!",
"imageUrl": "https://images.emojiterra.com/google/android-10/128px/1f916.png",
"imageStyle": "IMAGE",
},
"sections": [
{
"widgets": [
{
"textParagraph": {
"text": '<b>'+ (
itemResponse.getItem().getTitle() + ' ' + itemResponse.getResponse())',
}
}
]
},
{
"widgets": [
{
"buttons": [
{
"textButton": {
"text": "GO TO RESPONSE",
"onClick": {
"openLink": {
"url": e.response.getEditResponseUrl()
}
}
}
},
{
"textButton": {
"text": "GO TO FORM",
"onClick": {
"openLink": {
"url": FormApp.getActiveForm().getEditUrl()
}
}
}
}
]
}
]
}
]
}
]
}
options = {
'method' : 'post',
'contentType': 'application/json; charset=UTF-8',
'payload' : JSON.stringify(payload)
};
UrlFetchApp.fetch(url, options);
} catch(err) {
Logger.log('FormBot: Error processing Bot. ' + err.message);
}
} else {
Logger.log('FormBot: No Webhook URL specified for Bot');
}
}
The Form:
The Bot Response
The issue you're having it's because, inside your for loop, you are sending every time your payload using UrlFetchApp.fetch(url, options);, therefore you need to do it in this way:
// Previous stuff
for (var j = 0; j < itemResponses.length; j++) {
// Do something
}
// Do more stuff
UrlFetchApp.fetch(url, options);
Knowing that. The first thing I changed in your code, it was to create a payload object, which would possess a sections attribute that later will be populated.
var payload = {
"cards": [{
"header": {
"title": "TSFormBot",
"subtitle": "Form Notifications Bot",
"imageUrl": "https://raw.githubusercontent.com/techstreams/TSFormBot/master/notifications.png",
"imageStyle": "IMAGE"
},
"sections": []
}
]
};
Having the payload object, I created a function for populating the sections attribute, there you will have the for loop and after filling the object with all the responses, I added the two buttons:
/*
* Build Payload
*
* #param {Object} payload
* #param {ItemResponse[]} itemResponses
* #param {FormResponse} formResponse
*/
function populateCard(payload, itemResponses, formResponse){
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
payload["cards"][0]["sections"].push({
"widgets": [{
"textParagraph": {
"text": itemResponse.getItem().getTitle() + ' ' + itemResponse.getResponse()
}
}
]
});
}
payload["cards"][0]["sections"].push({
"widgets": [
{
"buttons": [
{
"textButton": {
"text": "GO TO RESPONSE",
"onClick": {
"openLink": {
"url": formResponse.getEditResponseUrl()
}
}
}
},
{
"textButton": {
"text": "GO TO FORM",
"onClick": {
"openLink": {
"url": FormApp.getActiveForm().getEditUrl()
}
}
}
}
]
}
]
}
);
return payload;
}
After all that, you will able to send the request using UrlFetchApp.fetch(url, options);. Your postToRoom(e) function would look like this:
/*
* Process Form Submission
*
* #param {Object} e - form submit event object
*/
function postToRoom(e) {
var formResponses = FormApp.getActiveForm().getResponses();
var formResponse = formResponses[formResponses.length-1];
var itemResponses = formResponse.getItemResponses();
formResponse.getEditResponseUrl()
var options, options, url;
url = PropertiesService.getScriptProperties().getProperty('WEBHOOK_URL');
if (url) {
try {
var payload = {
"cards": [{
"header": {
"title": "TSFormBot",
"subtitle": "Form Notifications Bot",
"imageUrl": "https://raw.githubusercontent.com/techstreams/TSFormBot/master/notifications.png",
"imageStyle": "IMAGE"
},
"sections": []
}
]
};
// Call this function to populate the card with the responses
var PopulatedPayload = populateCard(payload, itemResponses, formResponse);
options = {
'method' : 'post',
'contentType': 'application/json; charset=UTF-8',
'payload' : JSON.stringify(payload)
};
UrlFetchApp.fetch(url, options);
} catch(err) {
Logger.log('TSFormBot: Error processing Bot. ' + err.message);
}
} else {
Logger.log('TSFormBot: No Webhook URL specified for Bot');
}
}
Card Response
Docs
I used these docs to help you:
Class FormResponse.
Class Form.
Card Formatting Messages.
So in below code if i pass ancillaryProductInd as boolean code works, but when I pass it as a string, it does not work. In my understanding the below code should only work when I pass "false" string value and throw error on boolean. Any idea what is the issue here ?
main.ts
request
var rxInfos = [{
"ancillaryProductInd": "false",
"indexID": "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
}]
function subQuestionsHandler(rxInfos, data) {
const subQuestionArray = [];
rxInfos.forEach((rxInfo) => {
const subQuestion = {
question: []
};
if (rxInfo.ancillaryProductInd !== undefined && rxInfo.ancillaryProductInd === "false") {
subQuestion.question = data;
subQuestionArray.push(subQuestion);
}
});
return subQuestionArray;
}
subQuestionsHandler(rxInfos, [{
some data
}]);
Your example code works as expected with a string value "false" and doesnt run the if block when a boolean is used. See my example:
var rxInfos = [
{
ancillaryProductInd: "false",
indexID: "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
},
{
ancillaryProductInd: false,
indexID: "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
}
];
function subQuestionsHandler(rxInfos, data) {
const subQuestionArray = [];
rxInfos.forEach(rxInfo => {
const subQuestion = {
question: []
};
if (
rxInfo.ancillaryProductInd !== undefined &&
rxInfo.ancillaryProductInd === "false"
) {
console.log("no error");
subQuestion.question = data;
subQuestionArray.push(subQuestion);
} else {
console.log("throw error");
}
});
return subQuestionArray;
}
subQuestionsHandler(rxInfos, [
{
test: ""
}
]);
Hi i am getting the following response from server
{
"Application1": {
"status": "SUCCESS",
"comment": "A123456 added successfully to Application"
},
"Application2": {
"status": "SUCCESS",
"comment": "B67890 added successfully to Application"
}
}
i need to show a message based on the status , we are using angular and javascript i am unable to loop through and read the same, any help would be appreciated
The simpliest version i can imagine:
<script>
var json = {"Application1":{"status":"SUCCESS","comment":"A123456 added successfully to Application"},"Application2":{"status":"SUCCESS","comment":"B67890 added successfully to Application"}};
for(var t in json)
console.log(json[t]['status']);
</script>
You can read the values by parsing the string as json:
var obj = JSON.parse('{"Application1":{"status":"SUCCESS","comment":"A123456 added successfully to Application"},"Application2":{"status":"SUCCESS","comment":"B67890 added successfully to Application"}}')
Then you can get access the values as properties:
obj.Application1.status
First check the response is JSON object or string. If it is string, parse it to JSON. Then you can loop through it.
Use the following functions
isJson(your_response);
will return the JSON object or null.
var whatIsIt = function (object) {
var stringConstructor = "test".constructor;
var arrayConstructor = [].constructor;
var objectConstructor = {}.constructor;
if (object === null) {
return "null";
}
else if (object === undefined) {
return "undefined";
}
else if (object.constructor === stringConstructor) {
return "String";
}
else if (object.constructor === arrayConstructor) {
return "Array";
}
else if (object.constructor === objectConstructor) {
return "Object";
}
else {
return "don't know";
}
};
var isJson = function(o1)
{
// Validate JSON strings
var json_object = null;
var type = whatIsIt(o1);
switch(type)
{
case "String":
try{
json_object = JSON.parse(o1);
}catch (e){
return null;
}
break;
case "Object":
try {
JSON.stringify(o1);
json_object = o1;
}catch (e) {
return null;
}
break;
}
return json_object;
};
Assuming that the communication with the server is carried out in a separate angular service, you need to use ng-repeat and ng-if directives,
Please find the JSFiddle here :
http://jsfiddle.net/2ju3c6tc/1/
var module = angular.module("myModule", []);
module.service('serverCommunicator', ['$http',
function($http) {
//code to get the data from the server
//server Data would hold the JSON object after the AJAX req,however, it is assigned manually over here
this.serverData = {
"Application1": {
"status": "SUCCESS",
"comment": "A123456 added successfully to Application"
},
"Application2": {
"status": "SUCCESS",
"comment": "B67890 added successfully to Application"
}
};
}
]);
module.controller('myController', ['$scope', 'serverCommunicator',
function($scope, serverCommunicator) {
$scope.serverData = serverCommunicator.serverData;
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="myModule">
<div ng-controller="myController as myCont">
<div ng-repeat="dataElement in serverData">
<div ng-if="dataElement.status=='SUCCESS'">
This is success message :{{dataElement.comment}}
</div>
<div ng-if="dataElement.status=='FAILURE'">
This is failure message {{dataElement.comment}}
</div>
</div>
</div>
</div>