How to get JSON array on client_JS from server_JS? - javascript

From nodeJS (with Express) I try to send JSON_array in response to client JS:
asksJsonArray = JSON.parse(fs.readFileSync("tasks.json", 'utf-8'));
app.get('/getArr', function (req, res) {
readJsonContent();
res.json(JSON.stringify(TasksJsonArray)); //sending JSON array to client_JS in response
});
On client-side I want to get it, but nothing receive:
$.get('/getArr').success(function(res) {
var currencyData = JSON.parse(res);
if (!currencyData.rates) {
// possibly handle error condition with unrecognized JSON response
alert("currency data not found!");
} else {
taskArr = currencyData;
}
})
So I always receive msg 'currency data not found!' ...

res.json already converts the data to JSON, so you don't have to do it manually:
res.json(TasksJsonArray);
I believe this will also set the appropriate headers, so on the client, you don't have to explicitly parse the JSON, jQuery will do it for you:
$.get('/getArr').done(function(currencyData){
if (!currencyData.rates) {
// possibly handle error condition with unrecognized JSON response
alert("currency data not found!");
} else {
taskArr = currencyData;
}
});
Please note that assigning the response to a free variable is not really useful since you won't know when it's "safe" to access the variable. You might want to have a look at How do I return the response from an asynchronous call? .
This may still not work since currencyData might be a value that does not have a rates property. To learn how to correctly access the data, have a look at Access / process (nested) objects, arrays or JSON.

Alter res.json(JSON.stringify(TasksJsonArray)); to res.send(JSON.stringify(TasksJsonArray));.

Related

How to use GraphQL response as a variable in Javascript

I am new to GraphQL and I am have the query working as expected but I am having trouble working with the response.
Query
query {
all_assets(where: {title: "suppliestile-blt9607aa6a28539d2e.zip"}) {
items {
url
}
}
}
Calling Response
var jsondata = JSON.stringify(response.data);
console.log(jsondata);
This is giving me the following response
{"data":{"all_assets":{"items":[{"url":"https://assets.contentstack.io/v3/assets/blt15ad871ba49b8a41/blta52af33b959c061f/6352b5fb3bd922566d8d3f2d/suppliestile-blt9607aa6a28539d2e.zip"}]}}}
Essentially I would like to use the url value as a variable moving forward but I am having trouble extracting it from all of the nested objects and arrays does anyone have any advice to get me pointed in the right direction?
The answer won't differ because it's a Graphql request. It's just a response that you get through the request via response.data.
If you need to access specific object/property within the response , you need to use the index of the object, you can do
const url = response.data.all_assets.items[0].url;

Passing JSON array to cloud function node js

I am trying to convert a javascript object array to JSON to pass it with the POST request to the cloud function. However when I use the JSON.parse() function I get an error:SyntaxError: Unexpected token u in JSON at position 0
Can someone tell me what I'm doing wrong, this is my POST request:
const body = `{
"item":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}]
}`;
const init = {
method: 'POST',
body
};
fetch('https://us-central1-web-app-bbo-prod.cloudfunctions.net/TestObject', init)
.then((response) => {
return response.json(); // or .text() or .blob() ...
})
.then((text) => {
// text is the response body
})
.catch((e) => {
// error in e.message
});
and this my cloud function:
exports.TestObject = functions.https.onRequest(async(request, response)=> {
var corsFn = cors();
corsFn(request, response, async function() {
const myJSON = request.body.item;
console.log(JSON.parse(myJSON))
//console.log(item)
})})
TLDR:
Server: remove JSON.parse
Client: change init to
const init = {
method:'POST',
body:JSON.stringify(body),
headers: {
'Content-Type':'application/json'
}
}
Explained:
You've got three issues I see.
Anytime you see the following you are calling JSON.parse on invalid stringified JSON.
SyntaxError: Unexpected token u in JSON at position 0
First, req.body should already be JSON if everything's working properly and you received JSON. To call JSON.parse(req.body.item) is to pass an Object to a function that takes strings. You can just refer to req.body.item.
Second you have to make sure you're sending the correct body, you are passing an object as the body for the fetch function. I'm not familiar with the fetch function but a quick look at the Mozilla examples indicate that should it should be stringified, i.e. body:JSON.stringify(body). The object you pass likely is either converted to form data or has toString() called on it and you're sending [object Object].
// REPL
> ({foo:'bar'}).toString()
'[object Object]'
Third, you have to make sure it gets parsed properly on the backend.
According to the GCloud nodeJS docs the nodejs google cloud functions implement an endpoint for an Express Router.
Normally if you wanted to use JSON the way you are you would need the body parser BodyParser middleware. The examples here (GCloud HTTP Functions) indicate that the body-parser middleware is already instead and working based off of Content-Type header.
Since it's deciding whether to parse it as JSON based on content type you want to set the header in your fetch function as 'content-type':'application/json'.

How to handle Bad JSON in Firebase Cloud Functions?

I'm creating a firebase application which uses firebase-cloud-functions.
index.js
exports.auth = functions.https.onRequest((request, response) => {
response.status(200).send({
status : "Some Status"
});
}
This is very simple functions. I want to make a POST request on the endpoint with some payload. When I tested the API using Firebase Cloud Function Emulator and POSTman with bad json
{
"phoneNumber: "9632725300"
}
The server just crashed! My question is how to handle the bad request in firebase functions like these.
with this error
The server did not crash. You have sent it a bad request (malformed JSON) and it responded perfectly with a status code 400 which is "Bad Request".
You'd rather correct your JSON...
EDIT:
If you really wanted to be able to send invalid JSON, you could do so by circumventing the JSON body parser. To do so, you could either change your request to have a content-type header set to "text/plain". This content-type will use the text body parser, which will not parse any JSON.
Note that doing so will require you to handle the JSON parsing yourself, but will permit to handle to error yourself using a try-catch.
let json;
try {
json = JSON.parse(json);
} catch (e) {
// Handle JSON error.
}
Taken from https://firebase.google.com/docs/functions/http-events
What you're experiencing is not actually a server crash. In fact, technically, by using Cloud Functions, you don't have a server to crash. (For this reason they're called "Serverless Infrastructure") Each request / operation you perform on Cloud Functions is kind of like a brand new server. Which is actually what's fantastic about Cloud Functions in general. (This is an overly simplified explanation, I'd suggest reading up a bit more about it for a better in depth explanation)
That being said, from what I understand you're trying to figure out if the JSON you got is invalid (bad) or not. Occasionally, when I have to hook up a bunch of external services, rarely, but sometimes, they return a bad JSON that my Cloud Functions can't parse, therefore throws an error.
The solution is to put your JSON.parse in to a separate function and a try / catch block like this:
function safelyParseJSON (json) {
var parsed;
try {
parsed = JSON.parse(json);
} catch (e) {
// BAD JSON, DO SOMETHING ABOUT THIS HERE.
}
return parsed; // will be undefined if it's a bad json!
}
function doSomethingAwesome () {
var parsedJSON = safelyParseJSON(data);
// Now if parsedJSON is undefined you know it was a bad one,
// And if it's defined you know it's a good one.
}
With this helper function, if you have to deal with a lot of external JSON resources, you can easily determine if the JSON you're trying to parse is good, and if not, you can at least handle the error your way.
Hope this helps :)
{\n\t"phoneNumber: "9632725300"\n}
From the screenshot, I see that the JSON is invalid or malformed. It contains newline (\n) and tab space (\t) characters. Also, the key "phoneNumber" is not wrapped in double quotes, which again invalidates the JSON.
Here's a valid format of the JSON that the server should receive
{
"phoneNumber": "9632725300"
}

Uncaught (in promise) SyntaxError: Unexpected end of JSON input

I am trying to send a new push subscription to my server but am encountering an error "Uncaught (in promise) SyntaxError: Unexpected end of JSON input" and the console says it's in my index page at line 1, which obviously is not the case.
The function where I suspect the problem occurring (because error is not thrown when I comment it out) is sendSubscriptionToBackEnd(subscription) which is called in the following:
function updateSubscriptionOnServer(subscription) {
const subscriptionJson = document.querySelector('.js-subscription-json');
const subscriptionDetails = document.querySelector('.js-subscription-details');
if (subscription) {
subscriptionJson.textContent = JSON.stringify(subscription);
sendSubscriptionToBackEnd(subscription);
subscriptionDetails.classList.remove('is-invisible');
} else {
subscriptionDetails.classList.add('is-invisible');
}
}
The function itself (which precedes the above function):
function sendSubscriptionToBackEnd(subscription) {
return fetch('/path/to/app/savesub.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(subscription)
})
.then(function(response) {
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function(responseData) {
if (!(responseData.data && responseData.data.success)) {
throw new Error('Bad response from server.');
}
});
}
I have tried replacing single quotes with double quotes in the fetch call but that yields the same results.
I know that the JSON should be populated because it prints to the screen in the updateSubscriptionOnServer() function with subscriptionJson.textContent = JSON.stringify(subscription);, and I used that output in the google codelab's example server to receive a push successfully.
EDIT: Here is the JSON as a string, but I don't see a mistake in syntax:
{"endpoint":"https://fcm.googleapis.com/fcm/send/dLmthm1wZuc:APA91bGULRezL7SzZKywF2wiS50hXNaLqjJxJ869y8wiWLA3Y_1pHqTI458VIhJZkyOsRMO2xBS77erpmKUp-Tg0sMkYHkuUJCI8wEid1jMESeO2ExjNhNC9OS1DQT2j05BaRgckFbCN","keys":{"p256dh":"BBz2c7S5uiKR-SE2fYJrjPaxuAiFiLogxsJbl8S1A_fQrOEH4_LQjp8qocIxOFEicpcf4PHZksAtA8zKJG9pMzs=","auth":"VOHh5P-1ZTupRXTMs4VhlQ=="}}
Any ideas??
This might be a problem with the endpoint not passing the appropriate parameters in the response's header.
In Chrome's console, inside the Network tab, check the headers sent by the endpoint and it should contain this:
Example of proper response to allow requests from localhost and cross domains requests
Ask the API developer to include this in the headers:
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Credentials" : true
This happened to me also when I was running a server with Express.js and using Brave browser. In my case it was the CORs problem. I did the following and it solved the problem in my case:
(since this is an Express framework, I am using app.get)
-on the server side:
res.set({
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
});
-on client side I used Fetch to get data but disabled the CORS option
// mode: "no-cors" //disabled this in Fetch
That took care of my issues with fetching data with Express
This can be because you're not sending any JSON from the server
OR
This can be because you're sending invalid JSON.
Your code might look like
res.end();
One of the pitfalls is that returned data that is not a JSON but just a plain text payload regardless of headers set. I.e. sending out in Express via something like
res.send({a: "b"});
rather than
res.json({a: "b"});
would return this confusing error. Not easy to detect in network activity as it looks quite legit.
For someone looking here later. I received this error not because of my headers but because I was not recursively appending the response body to a string to JSON.parse later.
As per the MDN example (I've taken out some parts of their example not immediately relevant):
reader.read().then(function processText({ done, value }) {
if (done) {
console.log("Stream complete");
return;
}
result += chunk;
return reader.read().then(processText);
});
For my issue I had to
Use a named function (not an anonymous ()=>{}) inside the .then
Append the result together recursively.
Once done is true execute something else on the total appended result
Just in case this is helpful for you in the future and your issue is not header related, but related to the done value not being true with the initial JSON stream response.
I know this question has already been answered but just thought I add my thoughts.
This will happen when your response body is empty and response.json() is expecting a JSON string. Make sure that your API is returning a response body in JSON format if must be.

Cannot update Parse object via REST API

Right, so I'm simply trying to update my object via the REST API. My request succeeds, I get a 200 response back containing the latest updated timestamp, but the object's column value has not changed.
My Movies class has a title and a genre column, the rights on the class are set to public read write on all rows.
Here is some code
var data = {title:'The Revenant'};
qwest.put('https://api.parse.com/1/classes/Movies/myObjectId', JSON.stringify(data))
.then(function(xhr, response) {
console.log(response);
})
.catch(function(xhr, response, e) {
console.log(e);
});
The response I get back?
{"updatedAt":"2016-01-24T07:59:54.977Z"}
So the request succeeded but if I GET the object again or check in the Parse admin page, the object has not changed. What gives?
EDIT
FYI, if I use the Javascript SDK, I can update the model.
var Movies = Parse.Object.extend("Movies");
var query = new Parse.Query(Movies);
query.get(myObjectId, {
success: function (movie) {
movie.set("title", data.title);
movie.save();
},
error: function (object, error) {
console.log(error);
}
});
This updates the model. For my particular use case though, I would really prefer to use the REST API rather than the SDK, but I guess this means it is not a permissions issue or an id mismatch etc.,
code snippet
qwest.put('https://api.parse.com/1/classes/Movies/Dh7zjiP9KW', data, {dataType:"json",headers:{'x-parse-application-id':'XXX','X-Parse-REST- API-Key':'XXX'}})
.then(function(xhr, response) {
console.log(response);
})
.catch(function(xhr, response, e) {
console.log(e);
});
The response you're getting indicates that the object was updated successfully. Double check that you're looking at the correct object, and that the "updatedAt" field matches the response you saw earlier.
What happens if you fetch the object right away, using the same "qwest" client and https://api.parse.com/1/classes/Movies/myObjectId resource URL (with the correct object id)?
Try removing JSON.stringify(data) and just pass data,

Categories