Next.js API Route mysteriously modifying JSON payload - json

For some reason, when I send JSON formatted data through Postman as raw text, I have no issues. When I send the exact same data through Postman as raw JSON (the difference should only be that the content-type header is application/json instead of application/text), I end up with my double quotes stripped and my strings switched to single quotes.
Original payload example (Postman sends this):
{ "id": "blahblahbloo", "time": "hammer" }
Unintended transformation (NextJS receives this):
{ id: 'blahblahbloo', time: 'hammer' }
To be clear, I get the exact same thing (which is what I expect) when I send as raw text via Postman:
// Postman sends this and NextJs receives this when set to raw text
{ "id": "blahblahbloo", "time": "hammer" }
I'm not explicitly doing anything to read the content-type and transform the data. My endpoints with this issue is a NextJS Dynamic Route: https://nextjs.org/docs/api-routes/dynamic-api-routes

Next.js API routes have a built-in bodyParser middleware that will parse the incoming request's body based on its Content-Type header.
From the API Middlewares documentation (emphasis is mine):
API routes provide built in middlewares which parse the incoming
request (req). Those middlewares are:
req.cookies - An object containing the cookies sent by the request. Defaults to {}
req.query - An object containing the query string. Defaults to {}
req.body - An object containing the body parsed by content-type, or null if no body was sent
Sending the payload as application/json will have the API route convert the req.body to a JavaScript object, hence striping the double-quotes.
While the bodyParser middleware is automatically enabled by default, you can disable it if you want to consume the body yourself.
// In the API route
export const config = {
api: {
bodyParser: false
}
}

Related

Postman: POST request of nested JSON via form-data not working (while via raw-data ok)

I want to POST the following JSON-object via Postman:
{
"title": "test_title",
"date": "2021-12-31",
"attachments": [
{
"name": "test_attachment"
}
]
}
This works perfectly fine, when using Postman's raw input form for the request-body: I get a "201 Created"-response back.
However, when using the form-data to POST the data, I get the error "Invalid data. Expected a dictionary, but got str." (see also screenshot below) What am I doing wrong here? I tried all kind of other versions to enter the attachment-key:value pair but nothing worked so far
I managed to make it work! (note: I added some additional fields compared to the screenshot in question. See below for details:
You did nothing wrong.
If you want to make a request with json object, then you go with raw type (json) in postman.
If you want to upload file, then you use form-data
One more thing, status 201 means the request is succeed, your object has been created.
var express = require('express')
const multer = require('multer')
const upload = multer()
var app = express()
app.use(express.json());
app.post('/test',upload.none(), function (req, res, next) {
res.send(req.body)
})
app.listen(80, function () {
console.log('web server listening on port 80')
})
Above is a sample endpoint which works with both form-data and json , just do a post to http://localhost:80/test with both form data and raw json
you can see both will get parsed correclty
APIs are just abstraction , its like a function that takes in many attribute, how you parse it depends on the implementation ( how the api function is written) .
so answer is "Talk to the developer" on how the API is implemented and what it is supporting
I'm having issue in placing json into form format the way Daniel did in Postman. Need help in figuring out what is it required to place the cascaded json objects into form data format. Please see here that I'm trying to accomplish.
JSON Format (to be filled into Postman form-data section:
{
"primary_object": {
"child_object_1": [{"id": 12345678, "value": "abc"},{"id": 87654321, "value": "xyz"}],
"child_object_2": [
"first_val",
"second_val"
]
}
}

How to parse JSON object at server side?

I am trying to send data to a server (local rest API) from react using post request, if i send an object like this:
{key:"value"}
then i get this at the server:
{ '{"key":"value"}': '' }
It's converting the whole object into key-value pair.
How can i solve this issue?
axios.post('http://localhost:5000/animals', JSON.stringify(data))
.then((response)=>{
console.log(response);
});
If I don't stringify, then I get an empty object at the server, but if I do stringify, then I get this sort of object as mentioned above. Is there any way to convert it back to a normal object?
It looks like the server expects to get data in application/x-www-form-urlencoded encoding, not application/json.
Why?
application/x-www-form-urlencoded encoded data looks like
key1=value1&key2=value2&....
But values are optional, so
key1&key2=value2
works too.
You are sending {"key":"value"} which to the server looks like a key without a value. Since it looks like you have control over the server, change the server implementation to parse the request body as JSON instead. How to do that depends on the framework you are using on the server.
If you are using express.js, use bodyParser.json(). Alternatively send the data application/x-www-form-urlencoded encoded, not as JSON, as suggested by Chinedu.
Performing a POST request with axios
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Can you try constructing the data you want to send as the above exam, send to your api and see if the dummy data comes. No json parse or stringfy needed.
Are you using body-parser middleware in your nodejs express app?

AWS api gateway JSON-like body

I set up a POST ressource in API Gateway which invokes a Lamdba function, fine.
In the "integration request", for text/plain Content-type, I defined the following mapping :
#set($messageStr = $util.urlEncode($input.body))
{
"message" : "$messageStr"
}
Problem is : whenever I POST data with JSON reserved characters, the integration request mapping thows
{"message": "Could not process payload"}
Example : blablabla will be correctly passed through to lambda, not {blablabla nor a:e ...
This seems like that method urlEncode expects JSON data.
Any idea how to pass whatever body as pure text ?
Thanks

Should I put JWT on JSON as base64 string?

I design REST API for my site. I read some info about proper JSON-API. And now draft version is look like:
{
"data":
{
//data that I will send
},
"errors":"",
"meta":
{
"token": // auth info for ever request
{
// JWT token here
}
}
}
But I can't understand should I put JWT token as base64 string like:
"token" : "base64encodedstring"
or should I put JWT as nested object in "token"?
Also I have got question. Am I right understand that it's good practice to use once designed JSON-API everywhere? I mean that same JSON (with different data section will be used for auth, for data exchange and so on)
If the JWT is in compact serialization format (3 or 5 parts separated by dots), then it is not necessary to encoded it.
Otherwise, if it is in flattened or general serialization format (a JSON object), then you will have to encode it.

How can I get ServiceStack's Swagger implementation to use XML content-type?

I have a VERY basic ServiceStack experiment that uses Swagger for generating documentation. The service can be used with several different content-types (XML, JSON, etc.):
Default metadata page
However, I can only use content-type/json in the Swagger UI. Is there a configuration/attribute I can use, so that I can test the other content-types?
Swagger UI
You can't change what Content Type Swagger uses, but ServiceStack Services provides automatic Content Negotiation so you can query for XML by using an .xml extension, e.g:
/query.xml
Or specifying the format in the ?format= query string:
/query?format=xml
Or by adding the Accept: application/xml HTTP Request Header.
Swagger wont let change Content Types but you can use a more general purpose tool like ServiceStack's Postman support or Fiddler.
Modifying Swagger Response
I've just added a change in the latest v4.0.53 of ServiceStack that's now available on MyGet that lets you alter the Swagger Response returned by ServiceStack you can use to populate consumes and produces at both the API Declaration and Operation level with:
Plugins.Add(new SwaggerFeature {
ApiDeclarationFilter = x =>
x.Consumes = x.Produces = new[] { MimeTypes.Json, MimeTypes.Xml }.ToList(),
OperationFilter = x =>
x.Consumes = x.Produces = new[] { MimeTypes.Json, MimeTypes.Xml }.ToList()
});
But this doesn't look like it has much of an effect to the Swagger UI, the only change I can see is the body parameter in POST requests now let you send XML:
In the Swagger spec (generated by ServiceStack), you need to update produces for the endpoint to include both "application/xml" and "application/json" if you want both to appear in the dropdown menu in swagger-ui.
Here is an example:
"produces": [
"application/json",
"application/xml"
],
Ref: https://github.com/swagger-api/swagger-codegen/blob/master/modules/swagger-codegen/src/test/resources/2_0/petstore.json#L77
OpenAPI Spec produces: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields