I am trying to dynamically build an axios get request, and have currently hardcoded some values in my parameters array to test with like so:
const parameters = [
'table=cumulative',
'where=koi_disposition like \'CANDIDATE\' and koi_period>300 and koi_prad<2',
'order=koi_period',
'format=json'
];
let searchParameters = '';
const api = axios.create({
baseURL: 'https://exoplanetarchive.ipac.caltech.edu/cgi-bin/nstedAPI/nph-nstedAPI'
});
for (let element in parameters) {
if (element !== '') {
searchParameters += `?${parameters[element]}`;
}
}
I then add this query to my axios get request below:
export const getExoplanets = async () => {
try {
searchParameters = searchParameters.replace(/;/g, "");
console.log(`${searchParameters}`);
return await api.get(`${searchParameters}`);
// return await api.get(`?table=cumulative&where=koi_disposition like 'CANDIDATE' and koi_period>300 and koi_prad<2&order=koi_period&format=json`);
} catch (error) {
return error;
}
};
When the variable version runs the api returns the error:
ERROR
Error Type: UserError
Message: Constraint contains an illegal keyword: ";"
However when the commented out, hard coded version runs it works just fine. At some point an extra semicolon is being added to the request. I assume it is being added at the end, but I can't find where or how. Any ideas how to fix this?
Axios supports easy query parameters using the params config option.
Just provide an object of key / value pairs and Axios will do all the encoding for you
const params = {
table: "cumulative",
where: "koi_disposition like 'CANDIDATE' and koi_period>300 and koi_prad<2",
order: "koi_period",
format: "json"
}
return api.get("", { params })
// or return api.get("", { params: params })
This will send a request to
?table=cumulative&where=koi_disposition+like+%27CANDIDATE%27+and+koi_period%3E300+and+koi_prad%3C2&order=koi_period&format=json
it seem you having an issue in this bellow line you have used the \ rest of this you can wrap all the things in the double quote.
'where=koi_disposition like \'CANDIDATE\' and koi_period>300 and koi_prad<2',
"where=koi_disposition like 'CANDIDATE' and koi_period>300 and koi_prad<2",
Related
I am using the bubble.io plugin builder. To return a response under bubble.io's api connector, all parameters returned must have the prefix "p". In the following case, this returns the correct results for an api call.
const options = {
url: url
,method: method
,headers: {
"Content-Type": "application/json"
}
}
const response = context.request(options);
console.log(response);
/*
The model we will use
{
"mins": 5,
"price": "34823.91104827"
}
*/
var body = JSON.parse(response.body);
const {convert} = require('json-to-bubble-object');
let returnlist = []
returnlist.push( {
"_p_mins": body.mins.toString(),
"_p_price": body.price,
"_p_api_response": JSON.stringify(convert(body))
})
return {
"result": returnlist
}
This call generates the following response:
_p_api_response: "{"_p_mins":5,"_p_price":"36703.73207769"}"
_p_mins: "5"
_p_price: "36703.73207769"
What I am trying to do is use the module 'json-to-bubble-object' as returned in the _p_api_response parameter (which is a test parameter and is not actually needed) to return the data. This makes my call dynamic so I don't have to manually specify the parameters for each different api call.
Hence, I am trying to make the API call look something like this:
var body = JSON.parse(response.body);
const {convert} = require('json-to-bubble-object');
let returnlist = []
returnlist.push( JSON.stringify(convert(body))
)
return {
"result": returnlist
}
but this returns null results
_p_api_response: null
_p_mins: null
_p_price: null
can someone let me know how I can return the data generated from the convert function as a list as done in the first request? Thanks
EDIT: For clarification, the p prefix allows the response headers to be viewed in the bubble.io builder, as seen in the below image.
I dont have enough reputation to comment but
I am unable to repro your problem.
You can view my repro here:
https://runkit.com/runkitname/so-a-nodejs
const {convert} = require('json-to-bubble-object');
var body = {
"mins": 5,
"price": "34823.91104827"
}
body.api_response = JSON.stringify(convert(body))
let returnlist = []
returnlist.push(convert(body))
console.log({"result": returnlist})
console
{
result: [
{
_p_mins: 5,
_p_price: '34823.91104827',
_p_api_response: '{"_p_mins":5,"_p_price":"34823.91104827"}'
}
]
}
Lets presume I am sending a POST request to /api/products. My body is like below
{
"products":[
{
"id":"5f5065e44a12bd00232bcc6g",
"status":"true"
},
{
"id":"5f5065e44a12bd00232bcc6g",
"status":"true"
}
]
}
In my route I am trying to convert the above products to a JSON Object;
Below is my server code
const { products } = req.body;
console.log(JSON.parse(products));
but this gives me the error "message": "Something went wrong Unexpected token o in JSON at position 1"
How can i achieve this??
Cheers
Screenshots added
Tried below as well. But no luck
Nothing works.
const products = req.body;
console.dir(typeof products); // 'object'
console.dir(products); // { products: '[object Object]' }
const { products } = req.body;
console.dir(typeof products); // 'string'
console.dir(products); // '[object Object]'
postman developer console is as below. Doesnt seem to be an issue
{
"products":[
{
"id":"5f5065e44a12bd00232bcc6g",
"status":"true"
},
{
"id":"5f5065e44a12bd00232bcc6g",
"status":"true"
}
]
}
It's not a JSON object, JSON objects are surrounded by curly braces.
if you return
{"products": [ { "id":"5f5065e44a12bd00232bcc6g", "status":"true" }, { "id":"5f5065e44a12bd00232bcc6g", "status":"true" } ]}
then it will be worked.
The best thing to do would be to fix what you're sending to /api/products by putting {} around it, like this:
{
"products":[
{
"id":"5f5065e44a12bd00232bcc6g",
"status":"true"
},
{
"id":"5f5065e44a12bd00232bcc6g",
"status":"true"
}
]
}
Now it's valid JSON, and you can convert it via JSON.parse:
const obj = JSON.parse(req.body);
console.log(obj);
const { products } = obj;
or just
const { products } = JSON.parse(req.body);
Notice I'm using the entire body there. That will give you an object with a property (products) with the array of products. Alternatively, instead of parsing it manually, you could use middleware that would parse it automatically so that req.body is the parsed result, in which case it's just:
console.log(req.body);
const { products } = req.body;
If for some reason you can't send correct JSON, but it will always be in the form you've shown, you could add the {} afterward like this:
const obj = JSON.parse("{" + req.body + "}");
console.log(obj);
const { products } = obj;
or just
const { products } = JSON.parse("{" + req.body + "}");
but I strongly recommend not doing that, not least because you can't use middleware and sending malformed data around tends not to be ideal. Instead, send valid JSON in the first place.
Look at the content of your variable products, and your debugger.
In this line you're using an object destructuring assignment but the right hand side isn't an object, it's a string:
const { products } = req.body;
Try this instead:
const { products } = JSON.parse(req.body);
EDIT you appear to be using Express middleware or similar. There's a good chance that your object has already been converted from JSON so you just need your original line and not the JSON.parse line.
const { products } = req.body;
console.dir(products);
Figured it out.
Thanks to #T.j and #Alnitak was able to get this sorted. Used
let obj = req.body;
But i had an issue with my validator.
body('products')
.trim()
.not()
.isEmpty()
.withMessage('Custom product must have a main product'),
In the above code using .trim() converted the products into a string and once I removed the trim() it works perectly. Thanks all for the thoughts
Try with JSON.stringify()
Otherwise, maybe you were declaring an object (const { products }), try without the {}
I can't figure out how to URL encode array params in an elegant way, in order to send XHR requests from my Vue.js client to my Symfony PHP API.
For example i have this GET method endpoint:
/question/list?subjects={idSubject}
It lists Question entity items and optionally, accepts params in order to filter results by them (subjects in this case)
The desired one would be:
/question/list?subjects[]={idSubject}&subjects[]={idSubject}
I'm using Axios for Vue.js to perform XHR requests and i created a main class that implements the methods that i want.
As the get() method doesn't support 'data' property in config object, i implemented it at the same way of a POST call and then i process it in order to build the desired URL.
This is my Ajax.js file:
const ajaxRequest = (config) => {
const token = TokenStorage.get()
config.baseURL = '/ajax'
if (token) {
config.headers = {
'Authorization': 'Bearer ' + token
}
}
return Axios.request(config)
}
const Ajax = {
get: (endpoint, params = null, config = {}) => {
const querystring = require('querystring')
let url = endpoint
if (Array.isArray(params) && params.length) {
url += '?' + params.join('&')
} else if (typeof params === 'object' && params !== null && Object.keys(params).length) {
url += '?' + querystring.stringify(params)
}
config = {
...config,
...{
url: url,
method: 'get'
}
}
return ajaxRequest(config)
},
post: (endpoint, params, config = {}) => {
config = {
...config,
...{
url: endpoint,
method: 'post',
data: params
}
}
return ajaxRequest(config)
}
}
I know that I could pass this data by POST but, in order to follow restful design, i want to keep GET method and optional params can be included in the URL as GET params.
If it were me I'd build a JavaScript array then call JSON.stringify() on it... then URL encode the resultant string and attach it as the sole parameter... to be JSON parsed by your server side handler.
I'm in a similar situation and I couln't find a built in library for this.
the most elegant solution I've found so far is by adding
Array.prototype.encodeURI = function(name) {
prefix = `${name}[]=`;
return prefix + this.map(o => encodeURI(o)).join(`&${prefix}`);
}
now you can use it:
let subjects = ["First Subject", "Second Subject"];
let myquery = subjects.encodeURI("subjects")
console.log(myquery)
// 'subjects[]=First%20Subject&subjects[]=Second%20Subject'
Note:
For empty arrays (e,g: let arr = [];) this method responds with subjects[]=, which php reads as an array with a single empty string (e,g: print_r($_REQUEST["subjects"]) prints Array ( [0] => )).
I couldn't find a standard for sending empty arrays url encoded and you should handle that somewhere.
Expected query string:
http://fqdn/page?categoryID=1&categoryID=2
Axios get request:
fetchNumbers () {
return axios.get(globalConfig.CATS_URL, {
params: {
...(this.category ? { categoryId: this.category } : {})
}
})
.then((resp) => {
// console.log(resp)
})
.catch((err) => {
console.log(err)
})
}
As you can see, it works perfectly with just 1 value for 1 parameter, but if i wanted to make multiple values - it doesn't work, i've tried to use an array:
...(this.category ? { categoryId: [1, 2] } : {})
But it returns this way:
http://fqdn/page?categoryID[]=1&categoryID[]=2
So it just not working. Had a look at this issue: Passing an object with a parameter with multiple values as a query string in a GET using axios
But can't figure out, how he solved this problem.
You can use Axios's paramsSerializer to customize the serialization of parameters in the request.
Note that URLSearchParams serializes array data the way you're expecting:
const searchParams = new URLSearchParams();
searchParams.append('foo', 1);
searchParams.append('foo', 2);
console.log(searchParams.toString()); // foo=1&foo=2
So you could use that class in paramsSerializer as follows:
// my-axios.js
export default axios.create({
paramsSerializer(params) {
const searchParams = new URLSearchParams();
for (const key of Object.keys(params)) {
const param = params[key];
if (Array.isArray(param)) {
for (const p of param) {
searchParams.append(key, p);
}
} else {
searchParams.append(key, param);
}
}
return searchParams.toString();
}
});
// Foo.vue
import axios from './my-axios.js';
export default {
methods: {
async send() {
const { data } = await axios({
url: '//httpbin.org/get',
params: {
categoryId: [1, 2, 3]
}
});
// ...
}
}
}
demo
This is not an axios related issue. It depends on whether your backend service is able to understand query params in this fashion(seems to be framework dependent). From your question, I think it is not working when queryParams like following are sent
?categoryID[]=1&categoryID[]=2
and it expects
?categoryID = 1,2
What you can do is transform array to such string before passing it to params in axios. Update the following piece in your code and it should solve your problem.
...(this.category ? { categoryId: this.category.join(',') } : {})
Take a look at following thread
How to pass an array within a query string?
I am having a lot of trouble scanning and then using FilterExpression to filter based on a single value. I have looked at the api documentation and other stack overflow questions, but am still having trouble figuring the proper syntax for this. Since I am also using react and javascript for the first time, this may be a problem with my understanding of those.
Below is what I am trying to use as a filter expression. uploadId is the field name in the Dynamo database table and event.pathParameters.id is the variable that should resolve to the value that the scan results are filtered on.
FilterExpression: "uploadId = :event.pathParameters.id"
Below is the code in within context:
import * as dynamoDbLib from "./libs/dynamodb-lib";
import { success, failure } from "./libs/response-lib";
export async function main(event, context, callback) {
const params = {
TableName: "uploads",
FilterExpression: "uploadId = :event.pathParameters.id"
};
try {
const result = await dynamoDbLib.call("scan", params);
if (result.Item) {
// Return the retrieved item
callback(null, success(result.Item));
} else {
callback(null, failure({ status: false, error: "Item not found." }));
}
} catch (e) {
callback(null, failure({ status: false }));
}
}
Thank you for your help!
Always use Expression with ExpressionAttributeValues. params should look like this.
const params = {
TableName: "uploads",
FilterExpression: "uploadId = :uid",
ExpressionAttributeValues: {
":uid" : {S: event.pathParameters.id} //DynamoDB Attribute Value structure. S refer to String, N refer to Number, etc..
}
};