-
-
Notifications
You must be signed in to change notification settings - Fork 956
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JSON option when posting data #174
Comments
@paglias it is possible, but |
It would be a major change, but not necessarily a bad one. At least having the option to enable it would be nice. Like, if Edit - Tagging @sindresorhus, since it's his project |
@spencerhakim Can you provide a code example of how it would look like? |
Reopening, but we're not likely to do another major in the near future. |
Current way: var options = {
json: true, // if truthy, parse *response* as JSON
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify({ // have to manually stringify object in body
name: 'whatever',
category: 'toy',
description: 'Hello World'
})
};
got.post(`http://example.com/api/createThing`, options)
.then((resp) => {
// ...
}); Possible new way (should be functionally equivalent to the above): var options = {
json: { // typeof json === 'object', not 'boolean', so send body as JSON instead of form-encoded
name: 'whatever',
category: 'toy',
description: 'Hello World'
}
};
got.post(`http://example.com/api/createThing`, options)
.then((resp) => {
// ...
}); Coming from |
Wouldn't it make more sense to pass the object literal in |
Yes, but that approach would likely require a major version bump. |
@sindresorhus What about making the The current
The above example would JSON encode/decode the request/response body. |
Not interested adding a temporary workaround when it's possible for you to stringify it yourself. We'll add support for passing object literal in body when |
@sindresorhus now passing object literal in |
@floatdrop I don't really see the confusion.
|
@sindresorhus it is clear, that Maybe it is better way to choose serialization based on |
Hm, I didn't think of that use-case.
|
@sindresorhus The flexibility seems to be appropriate in this case. Switched to |
I just converted from Stringify JSON Objects and Arrays and set Content-Type // stringify object and array bodies
if (options.json === true && options.body && (typeof options.body === 'object' || Array.isArray(options.body))) {
options.headers = options.headers || {};
options.headers['Content-Type'] = 'application/json';
options.body = JSON.stringify(options.body);
} |
Since this is a very common use case in my experience and the json flag works very differently from request/request which is the dominant http / request lib. Similarly visionmedia/superagent doesn't require the coder do much thinking with regards to JSON posts. I think many coders will require the same 5 - 10 min of messing about before they realise you do it manually with got. Perhaps even running into an unexpected error. Adding documentation for this common use case makes a lot of sense to me. I think the cost is low, even if only considering the benefit to the maintainers not having to deal with people creating issues like this. Would a PR be welcome? Unrelated but the same question for adding an index to the documentation. PR welcome? ^^ Thanks for creating what will undoubtedly be my new http lib goto. |
Alex, I think you are on point. I too wrote a wrapper around got for |
PR welcome for the change described in #174 (comment). Would be nice to have this included in the next major version. |
After giving the code a thorough read (so concise<3) I can say I would love to take a stab at it @sindresorhus. I also feel I might be out of my depth with all the streaming going on. I'm hoping the greatest cats in nodejs won't mind that. Maybe good to summarize.
This poses a problem for people wanting to send a querystring but receive json and have it parsed. Which is to be solved as follows.
This does leave the hairy situation where a user sets both Maybe you're going on the assumption querystring and json would both require explicit setting to affect the request. In that case, what is to be the default behaviour of body? Pass to Final question, what about people wanting to send json but not receive it? Many will use Again, if it isn't too much trouble answering, I would love to take a stab at this PR ^^ |
There are a lot of valid what-if questions here. My fear is that we implement this or another approach, someone ends up not liking it, then we add another set of options to accommodate that use case, and soon the Alternatively, we could devise a plugin architecture, possibly via |
Hm. I think considering to generalize this case makes sense @MarkHerhold. I've also got to add that's a bigger PR than I think I can take on, and wouldn't without the cats weighing in, and they seem busy. I think I'll simply open a PR, making the most straightforward choices I can. I like the general idea of having optional pre / post request processing. I wouldn't know the best way to implement it. |
I thought about this quite a bit when making my first attempt at implementing and now am pretty convinced it's a bad idea. I think having the 'shortcut props' makes more sense. So form, lets you easily send application/x-www-form-urlencoded, maybe formData for multipart/form-data, JSON for application/json. That leaves parsing freed up to be a wholly separate thing. Creating a clear distinction between serializing and deserializing which we shouldn't mix I'd say. Most of the inspiration for this thinking comes from looking around, mostly at superagent. A small bonus is that you can start treating deserializing manually by specifying a parsing function or you can start looking at the content-type in the response headers for default behavior parsing which would make a lot of sense too. |
I feel we're overthinking it a bit here and trying to consider too many imaginary edge-cases. The JSON option is just meant to cover the common case. If someone wants more advanced configurability they can just not use it. Proposal:
I'm open to suggestions on how we could simplify this further. |
Fair enough Sindre. |
I want to suggest we support all inputs that |
👍
I'm not sure what this means. Can you elaborate? |
I like when things work the way I imagine them to work. When I use a request library, specify a body, and ask to stringify the body, I imagine it:
Current proposal: only accept a plain object. > qstr('alex')
''
> qstr(24)
''
> qstr(['alex'])
'0=alex'
> qstr({name: 'alex'})
'name=alex'
> qstr({name: null})
'name='
> qstr(null)
''
> qstr(undefined)
''
> jstr('alex')
'"alex"'
> jstr(24)
'24'
> jstr(['alex'])
'["alex"]'
> jstr({name: 'alex'})
'{"name":"alex"}'
> jstr(null)
'null'
> jstr(undefined)
undefined Proposals:
I vote 3 🙋. Sidenote: wouldn't mind leaving this out of the milestone. |
I vote
Really? I've never seen that before. |
Alright, I'll do 1. but when the people come knocking for us to be less opinionated and support what is valid JSON, I'm with them ✊. |
@alextes That's actually a good way to do development. Let's call it Complaint-Based-Development. It's so easy to try to solve every imaginary use-case and get bloated. Implementing the minimum and rather change later if many people complain means you only implement what most people need. |
@sindresorhus Complaint-Based-Development 😁. Maybe call it Wish-Based-Development ✨ instead 🙏. Fully agree with all your points! |
@sindresorhus So how to make a request with json content but response is a html? |
const instance = got.extend({
hooks: {
beforeRequest: [
options => {
options.body = JSON.stringify(options.body);
}
]
});
instance(url, options); |
I'd go with something simpler 😊: got(url, {
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(body);
}); |
Custom instances are even simpler ;) No need to set headers every time or stringify the body :P |
Alright, alright 😄 . Still like this version better in that case. No need to understand got's request lifecycle. Although, you got to hand it to you (pun intended?), not having to stringify the body is pretty cool 😎 . const jsonGot = got.extend({
headers: {
'content-type': 'application/json'
}
})
jsonGot({
url,
body: JSON.stringify(post)
}) |
Excuse me? what u discussed is requesting a json, but what I asked is post a json, responsed is html 😂 |
As far as I'm good with English, IOW you said to make a request which body is JSON, and the response body is HTML. So I think you're confused here :) |
Ah, we should've been a bit clearer @ash0080 . got(url, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(body);
}); However, |
Ahhha~ Sorry, I am messed up. what we discussed is right. |
@cocuba this is a veeerry old issue. I suggest you create a new one 😉 . To try and help you along a little. What it's saying is the response you got back is not a JSON body. Got tried to decode it but the first token, that is, the first character in the response body is not valid for a JSON body. You can use |
ohhh!!! thanks. the response is the problem, thanks |
Would it be possible to use the
json: true
option when posting data to setContent-Type
toapplication/json
and stringify the body withJSON.stringify
?The text was updated successfully, but these errors were encountered: