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 {}
Related
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",
I am using nodejs for the server.
Currently I have a Json in my project folder.
name.json
{
"name_English": "Apple",
"name_German": "Apfel",
"name_French": "Pomme"
}
When I send request to server, it returns:
GET http://localhost:3030/name
{
"name_English": "Apple",
"name_German": "Apfel",
"name_French": "Pomme"
}
But I found it is not convenient for frontend development.
Is there any way to do something like below?
GET http://localhost:3030/name?lang=en
{
"name": "Apple"
}
GET http://localhost:3030/name?lang=fr
{
"name": "Apfel"
}
Edit 1
The code of getting the Json in Feathers.js
name.class.js
const nameLists = require('../name.json')
exports.Test = class Test {
constructor (options) {
this.options = options || {};
}
async find (params) {
return nameLists
}
};
Edit 2
Is it possible to make name.json like this?
{
"name": ${name}
}
Edit 3
The reason I want to achieve above because I have to return whole Json file.
For the internationalization library, it seems needed to handle outside the JSON and I don't know what is the best practise to do so.
Here's a full demonstration with just express. (Hope that's ok.)
const express = require('express');
const app = express();
const port = 3030;
const nameLists = require('./name.json');
const unabbreviateLanguage = {
en: 'English',
de: 'German',
fr: 'French'
}
function filterByLanguage(obj, abbr) {
let language = unabbreviateLanguage[abbr];
let suffix = '_' + language;
let result = {};
for (let key in obj) {
if (key.endsWith(suffix)) {
let newkey = key.slice(0, -suffix.length);
result[newkey] = obj[key];
}
}
return result;
}
app.get('/name', (req, res) => {
res.json(filterByLanguage(nameLists, req.query.lang));
});
app.listen(port);
e.g.:
curl http://localhost:3030/name?lang=de
output:
{"name":"Apfel"}
The idea is to iterate over the keys of the input object and prepare an output object that only has keys that match the language suffix (then strip off that suffix). You'll likely want to either have a mapping of en -> English, or just use the key names that match the parameter e.g., rename name_English to name_en.
In FeathersJS, the params object of find will store the query string of the passed in URL. So if you call http://localhost:3030/name?lang=en, the params object will be :-
{
query: {
lang: 'en'
}
}
You can then use this information to determine which result from the JSON to return.
https://docs.feathersjs.com/guides/basics/services.html#service-methods
Your question appears to be two parts: handling queries, and handling the internationalization.
Handling the query:
Feathers presents queries through the context object at the following location:
context.params.query
Handling Internationalization:
There are many solid packages available for handling internationalization:
https://openbase.com/categories/js/best-nodejs-internationalization-libraries?orderBy=RECOMMENDED&
I'm receiving data with axios like this:
getData() {
Axios.get(
'/vue/get-data/',
{
params: {
categories: this.category,
activeFilters: this.activeFilters,
}
}
).then((response) => {
this.banners = response.data;
this.setBanner();
})
},
Then I get this:
When I try console.log(response.data.length) I get undefined. What could
be going on here very weird!
When I look in my vue-devtools banners has 2 objects:
So how can response.data.length be undefined?
You are getting object not array that why .length is not working, and you are getting as undefined
this.banners = response.data[0];// for first
Or loop over this, to get each object's data
for(var i in response.data){
console.log(response.data[i]);
}
If to get each value is not your purpose , and you want to just size check this answer
I have an array in JavaScript that I use JSON.stringify() on that ends up looking like this after:
[
{
"typeOfLoan":"Home"
},
{
"typeOfResidency":"Primary"
},
{
"downPayment":"5%"
},
{
"stage":"Just Looking"
},
{
"firstName":"Jared"
},
{
"lastName":"Example"
},
{
"email":"Jared#demo.com"
},
{
"cell":"8888888888"
},
{
"loanofficer":"Jim Loan"
}
]
I want the output to be a standard JSON object so that I can send it in a POST. Before this gets marked as duplicate, I have tried all of the answers I could possibly find already and they all end up not working or having syntax errors that I do not understand how to fix. This array is stored in variable jsonArray.
The array of objects, all with a single key, seems fishy. I suppose you want a single object literal with all the keys, which you can then send to you backend (and parse there). So first, reduce the many objects in a single one, then implement your ajax call to POST it to wherever. Here's how to reduce it:
let arr = [{"typeOfLoan":"Home"},{"typeOfResidency":"Primary"},{"downPayment":"5%"},{"stage":"Just Looking"},{"firstName":"Jared"},{"lastName":"Example"},{"email":"Jared#demo.com"},{"cell":"8888888888"},{"loanofficer":"Jim Loan"}];
let res = arr.reduce((a,b) => {
let key = Object.keys(b)[0];
a[key] = b[key];
return a;
}, {});
console.log(res);
Depending on what you use to send it to the backend, you might need to use JSON.stringify on res
Before stringifying, convert your request payload from an array to an object.
const arr = [{"typeOfLoan":"Home"},{"typeOfResidency":"Primary"},{"downPayment":"5%"},{"stage":"Just Looking"},{"firstName":"Jared"},{"lastName":"Example"},{"email":"Jared#demo.com"},{"cell":"8888888888"},{"loanofficer":"Jim Loan"}];
const payload = arr.reduce(function(acc, prev){
return Object.assign(acc, prev);
}, {});
console.log(payload);
I'm using npm module traverse to filter data coming from mongodb / mongoose.
I might get this data:
[ { rating: 5,
title: { da: 'Web udvikling', en: 'Web Development' } },
{ rating: 5, title: { da: 'Node.js', en: 'Node.js' } } ]
'da' and 'en' indicates languages. I use traverse to filter mongoose data after current language like this:
var filtered = filterLanguage(lang, results);
// filter json obj by language
var filterLanguage = function(language, obj) {
return traverse(obj).map(function (item) {
if (this.key === language) {
this.parent.update(item);
}
});
};
I then show this in my template:
res.render('index', {
skills: filtered.skills
});
Finally I display it in the jade view:
ul.list-group
each skill, i in skills
if i < 5
li.list-group-item.sidebar-list-item= skill.title
Unfortunately it's displayed with quotes:
<ul>
<li>'Web Development'</li>
<li>'Node.js'</li>
</ul>
These quotes are not there in the unfiltered data (results.skill.title.da). So traverse is adding them. I used the module with 'plain' json and it's working perfectly.
The mongoose data seems plain and simple but of course there are a lot of properties on the prototype. Also traverse stalls if I don't omit '_id' (type bson/objectid) property from result set.
So traverse seems to have problems with mongoose data... Why is this? And how can I fix it?
-- EDIT --
I found a solution:
Before filtering I do this:
var json = JSON.parse(JSON.stringify(results));
var filtered = filterLanguage(lang, json);
This removes the quotes, but I'm not sure exactly what it does. Somehow converting the mongoose result to JSON? An explanation would be highly appreciated.
Fields in Mongoose documents are getters/setters, which seem to confuse either traverse or Jade/Pug.
The shortest method I found that seems to fix all of your issues is pretty ugly:
var filtered = filterLanguage(lang, results.map(r => JSON.parse(JSON.stringify(r))));
A more elaborate version:
var filtered = filterLanguage(lang, results.map(r => {
let j = r.toJSON()
j._id = j._id.toString()
return j;
}));
It would have been helpful to see what is the body of filterLanguage exactly or understand why it's called twice but as it stands, I don't think you need to use the traverse package at all.
A function such as below should do the trick and I even expanded it to work if the data is more tree-like and not as flat as represented in your example.
const reduceByLang = (data, lang) => {
// Look for a `lang` key in obj or
// if not found but still an object, recurse
const reduceByLangObj = (obj) => {
Object.keys(obj).forEach((key) => {
if (obj[key] === null) {
return;
}
if (obj[key][lang]) {
obj[key] = obj[key][lang]; // replace with desired lang
} else if (typeof obj[key] === 'object') {
reduceByLangObj(obj[key]); // recurse
}
});
return obj;
};
if (Array.isArray(data)) {
return data.map(reduceByLangObj);
} else {
return reduceByLangObj(data);
}
};
See example in JS Bin.
Also, if possible at all and if you do this type of selecting very often, I would look into saving the data in a different structure:
{ ratings: x, locales: { en: { title: 'Y' }, { da: { title: 'Z' } } } }
maybe, so that you can pick the selected language easily either in the query itself and/or in the controller.
EDIT: Checking for null.