parse JSON object with value passed as single quote string - javascript

I an getting aws event parameter as follow in the lambda call.
let event = { pathParameters: '{"foo":"35314"}' }
When I am trying to validate the parameter in condition , it cant find foo key on pathParameters
Here my condition check
if (event.pathParameters && event.pathParameters.foo) {
//do something
} else {
console.log('fail');
}
It going in else condition . I tried JSON.parse(JSON.strinify(event)). It did not help. I do get the Object if I do JSON.parse(event.pathParameters).
Any way to resolve the issue on root level object.

No, you can't parse the event to get access to the '{"foo": "35314}'", you need to parse the event.pathParameters value to get the actual foo and its value, 35314
let event = { pathParameters: '{"foo":"35314"}' }
if (event.pathParameters && JSON.parse(event.pathParameters).foo) {
console.log("'foo' =", JSON.parse(event.pathParameters).foo);
} else {
console.log('fail');
}

This is because the data that you are getting has JSON as stringified in pathParameters, so you'll have to parse with that key something like
JSON.parse(event.pathParameters).foo

let event = { pathParameters: '{"foo":"35314"}' } // foo is a string
if (event.pathParameters) {
try {
const { foo } = JSON.parse(event.pathParameters);
// use foo
} catch (jsonError) {
console.log('There was some json parse error', jsonError);
}
} else {
console.log('fail');
}
You need to parse the data from event.pathParameters

function doSomething(event) {
let pathParametersObj = JSON.parse(event.pathParameters);
if (pathParametersObj && pathParametersObj.foo) {
//do something
console.log('pass');
} else {
console.log('fail');
}
}
let event1 = {
pathParameters: '{"foo":"35314"}'
}
let event2 = {
pathParameters: null
}
doSomething(event1);
doSomething(event2);

Related

Loop Inside function of React Component

(React web app development)
In order to check if the current stock status of products, I use ID of products to loop through json data.
I am trying to retrieve value of "DATAPAYLOAD" by key (id) from json (below). idsent is string passed from another component. But "if (Data.response[i].id === idsent)" this condition always appears to be false because I got "failed" in console.
That would be really helpful if someone could take a look at the following code and give me some sujections, thanks in advance!
onButtonClicked = () => {
const idsent="D56F36C6038DFC8244F"
for (var i = 0; i < Data.response.length; i++) {
if (Data.response[i].id === idsent) {
name = Data.response[i].DATAPAYLOAD;
const word = '<INSTOCKVALUE>INSTOCK</INSTOCKVALUE>';
if (name.includes(word)) {
return true;
}
else {
return false;
}
}
console.log("failed");
}
The following is part of the json data that is requested through fetch get-method.
Data= {
"code": 200,
"response": [
{
"id": "CED62C6F96BD0E21655142F",
"DATAPAYLOAD": "<AVAILABILITY>\n <CODE>200</CODE>\n
<INSTOCKVALUE>OUTOFSTOCK</INSTOCKVALUE>\n</AVAILABILITY>"
},
{
"id": "D56F36C6038DFC8244F",
"DATAPAYLOAD": "<AVAILABILITY>\n <CODE>200</CODE>\n
<INSTOCKVALUE>LESSTHAN10</INSTOCKVALUE>\n</AVAILABILITY>"
},
{
"id": "4536C9E608B563A749",
"DATAPAYLOAD": "<AVAILABILITY>\n <CODE>200</CODE>\n
<INSTOCKVALUE>INSTOCK</INSTOCKVALUE>\n</AVAILABILITY>"
},
{
"id": "3A576872130625CABFADEE68",
"DATAPAYLOAD": "<AVAILABILITY>\n <CODE>200</CODE>\n
<INSTOCKVALUE>INSTOCK</INSTOCKVALUE>\n</AVAILABILITY>"
}
]
}
Thank you again.
You probably wanted console.log("failed"); outside of the for loop like the following (so that it only executes once all the data is processed):
onButtonClicked = () => {
const idsent="D56F36C6038DFC8244F"
for (var i = 0; i < Data.response.length; i++) {
if (Data.response[i].id === idsent) {
name = Data.response[i].DATAPAYLOAD;
const word = '<INSTOCKVALUE>INSTOCK</INSTOCKVALUE>';
if (name.includes(word)) {
return true;
}
else {
return false;
}
}
}
console.log("failed");
When the fetch is successful, You need to read and parse the data using json(). Pleas read this
onButtonClicked = async () => {
const idsent="D56F36C6038DFC8244F"
Data = await Data.json(); // json() will create a promise
for (var i = 0; i < Data.response.length; i++) {
if (Data.response[i].id === idsent) {
name = Data.response[i].DATAPAYLOAD;
const word = '<INSTOCKVALUE>INSTOCK</INSTOCKVALUE>';
if (name.includes(word)) {
return true;
}
else {
return false;
}
}
console.log("failed");
}
The reason you get failed, is because the first time through, the ID does not match the one sent, so it console logs the "failed" message. Then the second time through the for loop it matches the data, and then hits the next if, which checks for the value. Since the value you are searching for is included in the data, it returns true and the for loop is exited. The reason you see the fail log is because you are logging when the id doesn't match and there are 3 records in that array where the id don't match, the first one being one of them.

Is there a way to hold references to objects without interfering with their regular garbage collection?

I'm trying to make a signal based system for my Javascript application and i have something similar to this:
class EventHubListener {
constructor(eventName, callback, errorHandling) {
this.eventName = eventName;
this.callback = callback;
this.errorHandling = errorHandling;
}
}
class EventsHub {
constructor() {
this.listeners = [];
this.idgen = 0;
this.defaultErrorHandler = null;
}
registerListener(listenerInstance) {// EventHubListener
this.listeners.push(listenerInstance);
return listenerInstance.id = ++idgen;
}
register(eventName, callback, errorHandling) {
return registerListener(new EventHubListener(eventName, callback, errorHandling));
}
watchRemoteChange(type, field, callback, handling) {
return register('EvtRemoteStateChange', (data)=> {
if(!data || data.ObjectType !== type || !data.ChangedObject)
return;
callback(data.changedObject.id, data.ChangedObject[field]);
}, handling);
}
unregisterListener(id) {
this.listeners = this.listeners.filter(i=> i.id != id);
}
raise(eventName, data) {
this.listeners.forEach(l=> l.eventName === eventName, listener=> {
try {
if(listener.eventName === eventName)
listener.callback(data);
} catch(err) {
if(listener.errorHandling) {
try {
listener.errorHandling(err);
} catch(internalError) {
this.handleError(internalError);
}
} else {
this.handleError(err);
}
}
});
}
handleError(err) {
if(this.defaultErrorHandler) {
try {
this.defaultErrorHandler(err);
} catch(errorHandlingError) {
console.trace('Error in the default error handling routine', err, errorHandlingError);
}
} else {
throw internalError;
}
}
}
// use
hub.watchRemoteChange('Products', 'SellingPrice', (id, value)=> {
console.writeLine(`Product ${id} has changed price to ${value}!`);
});
My problem here is that I suppose that this "use" example will make the Hub class hold a reference to this annonymous function:
(id, value)=> {
console.writeLine(`Product ${id} has changed price to ${value}!`);
}
Which in this example doesn't seem a big problem, but it could be using values from the closure which would be eventually collected in case the user class is collected (I guess?), the thing I need here is a way to detect that the user class has been disposed and make the hub class stop holding them or their closures and possibly avoid executing broken closures, is there a way to do that in the library side or do I have to manually always manage unregistering my listeners from user code?

Calling Json Objects With Parameters Passed to Function

I've run into an interesting dilemma- I want to write a function which, given a couple parameters, will return an object/parameter in a JSON response based on the value of another.
Snippet 1 shows a way that I could do it with simple case checking:
function callf() {
return f("name", "project_id", "sampleName");
}
function f(Where, Return, Is) {
var options = {
"option1": "asdf",
"option2": "asdf"
}
var url = "..."
var response = UrlFetchApp.fetch(url, options);
var jsonResponse = JSON.parse(response.getContentText());
for (i in jsonResponse) {
if (Where == "object1") {
//Instead of dynamically calling the object, use case testing to call the desired object.
if (jsonResponse[i].object1 == Is) {
if (Return = "returnValue1") {
return jsonResponse[i].returnValue1;
} else if (Return = "returnValue2") {
return jsonResponse[i].returnValue2;
}
}
} else if (Where == "object2") {
if (jsonResponse[i].object2 == Is) {
if (Return = "returnValue1") {
return jsonResponse[i].returnValue1;
} else if (Return = "returnValue2") {
return jsonResponse[i].returnValue2;
}
}
}
}
However, with doing it the way above, I have to account for every possible object that the json response contains, that would be a pain. I want to find an alternative where I can simply pass the a string representing the object I want to return from a function like the snippet below:
function callf(){
return f("name","project_id","sampleName");
}
function f(Where,Return,Is){
var options = {
"option1":"asdf",
"option2":"asdf"
}
var url = "..."
var response = UrlFetchApp.fetch(url,options);
var jsonResponse = JSON.parse(response.getContentText());
for(i in jsonResponse){
if(jsonResponse[i].(Where)==Is){
return jsonResponse[i].(Return);
}
}
}
How might I accomplish this?
Just like you're accessing json with i variable as key using square brackets,
for(var i in jsonResponse){
if(jsonResponse[i][Where]==Is){
return jsonResponse[i][Return];
}
}

API Key with colon, parsing it gives TypeError: forEach isn't a function

I'm trying to use New York Times API in order to get the Top Stories in JSON but I keep on getting a:
Uncaught TypeError: top.forEach is not a function
I feel like there's something wrong with the API key since it has : colons in the url. I even tried to encode it with %3A but it still doesn't work.
This is the basic url:
http://api.nytimes.com/svc/topstories/v2/home.json?api-key={API-KEY}
My function that grabs the data from the url:
```
function topStories(topStoriesURL) {
$.getJSON(topStoriesURL, function(top) {
top.forEach(function(data) {
link = data.results.url;
cardTitle = data.results.title;
if(data.results.byline == "") { postedBy = data.results.source; }
else { postedBy = data.results.byline; }
imgSource = data.results.media[0].media-metadata[10].url;
createCardElements();
});
});
}
I console.log(url) and when I click it inside Chrome console, it ignored the part of the key that comes after the colon. I've been debugging, but I can't seem to figure out the error.
Here is a version of the code that works.
function topStories(topStoriesURL) {
$.getJSON(topStoriesURL, function(data) {
if (data.error) {
alert('error!'); // TODO: Add better error handling here
} else {
data.results.forEach(function(result) {
var link = result.url,
cardTitle = result.title,
postedBy = result.byline == "" ? result.source : result.byline,
hasMultimedia = (result.multimedia || []).length > 0,
imgSource = hasMultimedia ? result.multimedia[result.multimedia.length - 1].url : null;
createCardElement(link, cardTitle, postedBy, imgSource);
});
}
});
}
function createCardElement(link, title, postedBy, imgSource) {
// create a single card element here
console.log('Creating a card with arguments of ', arguments);
}
topStories('http://api.nytimes.com/svc/topstories/v2/home.json?api-key=sample-key');
You are most likely going to need to do a for ... in loop on the top object since it is an object. You can not do a forEach upon on object the syntax would probably look like this:
function topStories(topStoriesURL) {
$.getJSON(topStoriesURL, function(top) {
for (var datum in top) {
link = datum.results.url;
cardTitle = datum.results.title;
if(datum.results.byline == "") { postedBy = datum.results.source; }
else { postedBy = datum.results.byline; }
imgSource = datum.results.media[0].media-metadata[10].url;
createCardElements();
});
});
}
Heres the documentation on for...in loops

Nicer way to get nested object attributes

Often in a response from a remote API call, I receive nested objects:
var response = {
data : {
users : [
{
name : 'Mr. White'
}
]
}
}
I want to check whether the first user's name is 'Mr. White', and would naturally want to write something like.
var existed = response.data.users[0].name === 'Mr. White'
However I cannot be sure if all the objects are present, so to avoid exceptions instead I end up writing:
var existed = response && response.data && response.data.users && response.data.users[0].name === 'Mr. White'
Is there a nicer way to do this? Another ugly option that comes to mind is:
var existed = false;
try {
var existed = response.data.users[0].name === 'Mr. White';
} catch(e) { }
In addition to vanilla javascript, I usually have underscore.js and jquery available too.
Edit:
Oops, noticed I asked a dupe of javascript test for existence of nested object key.
An interesting option based on those answers is:
var existed = (((response || {}).data || {}).users || [{}])[0].name === 'Mr. White';
You could hide this naughty try/catch block inside a function like this one :
function resolve(root, path){
try {
return (new Function(
'root', 'return root.' + path + ';'
))(root);
} catch (e) {}
}
var tree = { level1: [{ key: 'value' }] };
resolve(tree, 'level1[0].key'); // "value"
resolve(tree, 'level1[1].key'); // undefined
More on this : https://stackoverflow.com/a/18381564/1636522
I would use the try catch approach but wrap it in a function to hide the ugliness.
Instead of a try/catch, this should be done via checking whether each level in the object is defined or not.
go for
if(typeof(response)!="undefined"
&& typeof(response.data)!="undefined"
&& typeof(response.data.users)!="undefined"
&& typeof(response.data.users[0])!="undefined"
&& typeof(response.data.users[0].name)!="undefined"
) {
//executes only if response.data.users[0].name is existing
}
Here is a function which I used in one of my projects http://jsfiddle.net/JBBAJ/
var object = {
data: {
users: [
{
firstName: "White"
},
{
firstName: "Black"
}
]
}
}
var read = function(path, obj) {
var path = path.split(".");
var item = path.shift();
if(item.indexOf("]") == item.length-1) {
// array
item = item.split("[");
var arrayName = item.shift();
var arrayIndex = parseInt(item.shift().replace("]", ""));
var arr = obj[arrayName || ""];
if(arr && arr[arrayIndex]) {
return read(path.join("."), arr[arrayIndex]);
} else {
return null;
}
} else {
// object
if(obj[item]) {
if(path.length === 0) {
return obj[item];
} else {
return read(path.join("."), obj[item]);
}
} else {
return null;
}
}
}
console.log(read("data.users[0].firstName", object)); // White
console.log(read("data.users[1].firstName", object)); // Black
console.log(read("data.test.users[0]", object)); // null
The idea is to pass your path as a string along with your object. The idea was to prevent the throwing of an exception and receive just null as result of the path is wrong. The good thing is that the function works with every path and you don't need to write long if statements.

Categories

Resources