How to add nested object to fetch POST body? - javascript

Given a simple fetch request i.e.
fetch('https://api.com/endpoint', {
method: "POST"
});
Is it possible / how can following object be converted to query params / query string to append to the fetch request? Most methods online recommend using new URLSearchParams helper, however it doesn't seem to work with nested objects and when converted to string these nested objects are returned as [Object object] string. Ideal solution should not rely on any third party packages.
{
side: 'buy',
symbol: 'AAPL',
type: 'market',
qty: '2',
time_in_force: 'gtc',
order_class: 'bracket',
take_profit: {
limit_price: '200'
},
stop_loss: {
stop_price: '200'
}
}

Form your fetch request like this:
fetch('https://api.com/endpoint', {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(dataYouWannaPost)
});

Related

Sending Object Arrays as JSON using FormData

I am sending a FormData object to an endpoint. A phone number needs to be formatted as this JSON:
"phone": [{"type":"main", "value":"#"}, ...] or it gets rejected. A single object with a two-pair of keys and values in an array.
const doStuff = () => {
const formData = new FormData()
**Have tried below for setting key/value of phone object**
// Attempt 1
formData.set('phone', [{ type: 'main', value: '313-555-2121' }])
// Returns:
"phone":"[Object Object]"
// Attempt 2
formData.set(
'phone',
JSON.stringify([{ type: 'main', value: '313-555-2121' }])
)
// Returns
"phone":"[{\"type\":\"main\",\"value\":\"313-555-2121\"}]"
// Format as single "fields" object and stringify (results in fields: {...stuff}), API needs this.
const formattedForApi = JSON.stringify({fields: Object.fromEntries(formData.entries())})
// MAKE POST REQUEST...
}
The API errors on both of my attempts above. Complaining of an invalid first value which needs to be "main". Am I missing something with how stringify is affecting the data that is actually being sent?
For those wondering, the API is Podio
Digging into the PHP SDK code, it seems you're supposed to send the fields as plain old JSON and definitely not double-encoded
const formattedForApi = JSON.stringify({
fields: {
phone: [
{
type: "main",
value: "313-555-2121",
},
],
},
});
fetch(`/item/app/${app_id}/`, {
method: "POST",
body: formattedForApi,
headers: {
authorization: `OAuth2 ${token}`,
"content-type": "application/json",
},
});
Sending arrays as JSON in FormData is possible, but it requires encoding the arrays into strings before adding them to the FormData object. Here's an example in JavaScript:
const formData = new FormData();
const array = [1, 2, 3];
// Encode the array into a string
const encodedArray = JSON.stringify(array);
// Add the encoded array to the FormData object
formData.append("array", encodedArray);
// Send the FormData object in an HTTP request
fetch("https://example.com/api", {
method: "POST",
body: formData
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
On the server-side, you can decode the string back into an array and use it as needed. The specific implementation will depend on the server-side language you're using.

Delete request api showing error in console when trying to delete an array of id's

Im trying to delete an array of id's by implementing a handler that takes a query parameter. I previously implemented a delete api function that takes one id and deletes it. However, now I have a new endpoint that I created that will clear the whole array. The new endpoint is:
The id's in the endpoint above are just dummy ones to show you how it is supposed to take the id's.
The configIds are passed as query parameters,and the response would be something like this:
So what I did was add the new endpoint to the existing delete api function that currently takes one configId. So:
async function deleteConfig(configId) {
const options = {
method: 'DELETE',
headers: {
'content-type': 'application/json'
},
url: configId.includes(',') ? `/api/v1/algo/configs?configIds=${configId}` : `${ALGOS_API_ROOT}/configs/${configId}`
};
return axios(options);
However, I am getting error here:
api/v1/private/api/v1/algo/configs?configIds=41,40,38,23,22 404 (Not Found)
As you can see, the id's are being passed in. But theres an error. Any help would be appreciated. Thanks!
Send the array of id's in the body of the request.
async function deleteConfig(configId) {
const options = {
method: 'DELETE',
headers: {
'content-type': 'application/json'
},
url: `${ALGOS_API_ROOT}/configs`,
data: {
ids: [1, 2, 3]
}
};
return axios(options);
}

Error sending Content_Tags while posting a video using FB API

I have tried many different ways but to no avail
API Spec - https://developers.facebook.com/docs/graph-api/reference/page/videos/
Param - content_tags ( list ) --> is what required
Below is my form data that is being posted
const formData = {
file_url: postOptions.filepath,
title: postOptions.title,
description: postOptions.description,
content_tags: ['tags', 'hello', 'hi']
};
HTTP Request Options
const options = {
url: https://graph-video.facebook.com/v9.0/${pageId}/videos?access_token=${accessToken},
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
},
formData,
};
Error response returned.
{"error":
{
"message":"(#100) Param content_tags[0] must be a valid ID string (e.g., \"123\")",
"type":"OAuthException",
"code":100,
"fbtrace_id":"ANoCbTSnh4uL960SjyE6XBV"
}
}
As per documentation, seems it has to be not just any string but NUMBER string which are predefined IDs of the tag list<numeric string>
From documentation
Tags that describe the contents of the video. Use search endpoint with type=adinterest to get possible IDs.
Example:
~~~~
/search?type=adinterest&q=couscous
~~~~
Here's full path of the above example shown by facebook, how you can get some IDs:
https://graph.facebook.com/search?type=adinterest&q=​"home"&limit =10&access_token={{access_token}}

Send nested json data with get method using axios

I am trying to send a nested json data with get method using axios, but the problem is that the backend considers the children as a string.
const TOKEN = "token"
const config = {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': TOKEN,
},
data: {},
params: {
"page_id": 1,
"filter": {
"search": "name"
}
}
};
axios.get("http://localhost/api/pages", config)
What I get if I want to print filter in backend:
"{"search": "name"}"
You may have two options:
1- The first option is to decode the string you receive to json.
e.g.
---json_decode() in php
--- JSONObject() in java
--- JSON.parse() in nodejs
or any other method depending on your backend language...
2- The second option is to send your object in this format:
params: {
"page_id": 1,
"filter[search]": "name"
}
And pay attention not to put search in quotes!
You can use req.query on the server side:
function get(req, res, next) {
const { filter } = req.query;
console.log(filter);
...
}
Do a JSON.parse() of your Request.query.filter. Note that Request should be the request variable in your backend.

HTTP params entries sharing the same key

This Meteor server code uses HTTP 1.1.7 to make a POST request to match what I did using java but I can not figure out how to include more than one entry into the request params which have the same key.
//in java 'working'
HttpParams javaParams = new HttpParams();
javaParams.add('food','milk')
javaParams.add('food', 'water')
javaParams.add('food', 'ice')
javaParams.encodeParameters("UTF-8");
//in javascript 'not working'
let headerObject {
"Content-Type" : "application/x-www-form-urlencoded",
'Accept-Language': 'en-US,en;q=0.5'
and others
}
const response = HTTP.call('POST', myUrl, {
timeout: 30000,
headers: headerObject,
params: {
'food': 'milk',
'food': 'water',
'food': 'ice'
}
});
//also tried these but server returned status code 500
food: ['milk', 'water', 'ice']
'food[]': ['milk', 'water', 'ice']
How can it this be done? Thanks
In JavaScript, just use an array:
const response = HTTP.call('POST', myUrl, {
timeout: 30000,
headers: headerObject,
params: {
food: ['milk', 'water', 'ice']
}
});
However, different languages on the server side use different mechanisms to handle parameter arrays. While Java should work with the above code, PHP for example needs the parameter name to contain square brackets, so the call would need to be
const response = HTTP.call('POST', myUrl, {
timeout: 30000,
headers: headerObject,
params: {
'food[]': ['milk', 'water', 'ice']
}
});
In the current case, the server side seems to expect each entry in a separate line of the request content as key=value pairs which each key being 'food'. Regrettably, this cannot be done with an JavaScript array nor with a JavaScript object.
To circumvent this problem, we use data instead of params. This prevents HTTP.call() from creating data from the given params. It only requires us to handle concatenation of the parameters ourself:
const response = HTTP.call('POST', myUrl, {
timeout: 30000,
headers: headerObject,
data: "food=milk\nfood=water\nfood=ice"
});

Categories