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

Query params not serializes as expected #3740

Closed
sporto opened this Issue Aug 24, 2013 · 36 comments

Comments

@sporto

sporto commented Aug 24, 2013

Angular serializes query strings in a particular way that many backend frameworks (including Rails) don't understand. jQuery param on the other hand has been the standard for this for years.

Example 1

var params = {
    arr: [1,2,3]
}

Angular serializes to

?arr=1&arr=2&arr=3

Jquery.param serializes to

arr%5B%5D=1&arr%5B%5D=2&arr%5B%5D=3 

// which is equivalent to
// arr[]=1&arr[]=2&arr[]=3 

Example 2

var params = {
    obj: {
        foo: 1          
    }
}

Angular serializes to:

obj=%7B%22foo%22:1%7D

// equivalent to
// obj={"foo":1}

jQuery.param serializes to

obj%5Bfoo%5D=1 

// which is eq to 
// obj[foo]=1 

There are several closed issues related to this, but this seems to be a common problem, jquery.param looks likes the expected behaviour.

#1363
#3121
#1640

Some of the conversation on these issues seems to imply that this has been done, but I tested this using Angular 1.2 with the same results as before.

Please lets consider making Angular serialization equivalent to jQuery.param

Thanks

@sporto

This comment has been minimized.

Show comment
Hide comment
@sporto

sporto Aug 24, 2013

This PR #3696 might fix this, will test it later

sporto commented Aug 24, 2013

This PR #3696 might fix this, will test it later

@Nitrodist

This comment has been minimized.

Show comment
Hide comment
@Nitrodist

Nitrodist Sep 10, 2013

Contributor

+1

Contributor

Nitrodist commented Sep 10, 2013

+1

@mustmodify

This comment has been minimized.

Show comment
Hide comment
@mustmodify

mustmodify commented Sep 25, 2013

+1

@ifeltsweet

This comment has been minimized.

Show comment
Hide comment
@ifeltsweet

ifeltsweet Dec 2, 2013

Please fix this.

ifeltsweet commented Dec 2, 2013

Please fix this.

@PanfilovDenis

This comment has been minimized.

Show comment
Hide comment
@PanfilovDenis

PanfilovDenis commented Feb 12, 2014

+1

@tanguyantoine

This comment has been minimized.

Show comment
Hide comment
@tanguyantoine

tanguyantoine commented Feb 13, 2014

+1

@Zohaibaig

This comment has been minimized.

Show comment
Hide comment
@Zohaibaig

Zohaibaig commented Feb 19, 2014

+1

@kwoon

This comment has been minimized.

Show comment
Hide comment
@kwoon

kwoon commented Feb 21, 2014

+1

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Feb 21, 2014

Contributor

This is silly. If you know you're dealing with a backend which understands that style of query, just append "[]" to the param name. There's nothing in any of the RFCs regarding URI construction or parsing which makes any statement about a special meaning of "[]". This feels like a wontfix, really.

Contributor

caitp commented Feb 21, 2014

This is silly. If you know you're dealing with a backend which understands that style of query, just append "[]" to the param name. There's nothing in any of the RFCs regarding URI construction or parsing which makes any statement about a special meaning of "[]". This feels like a wontfix, really.

@pkozlowski-opensource

This comment has been minimized.

Show comment
Hide comment
@pkozlowski-opensource

pkozlowski-opensource Feb 21, 2014

Member

@caitp this one is coming back over and over again so at one point I was thinking of abstracting this requests params serialization (and probably parsing) part into a service and thus allow people to swap implementation to match their backend. This should be rather simple to do.

Adding [] is definitively and option, just a bit of pain when you've got your object ready.

Member

pkozlowski-opensource commented Feb 21, 2014

@caitp this one is coming back over and over again so at one point I was thinking of abstracting this requests params serialization (and probably parsing) part into a service and thus allow people to swap implementation to match their backend. This should be rather simple to do.

Adding [] is definitively and option, just a bit of pain when you've got your object ready.

@sporto

This comment has been minimized.

Show comment
Hide comment
@sporto

sporto Feb 21, 2014

@caitp I don't see how this is a silly request, serialization is a basic building block that many libraries build on top. Many time you are high in an abstraction that uses the Angular serialization underneath. So what you are proposing is not a viable option.

Also appending [] only deals with array serialization. jQuery params also makes object serialization different, see above.

Probably asking just to change this completly is an unreasonable request as people using Angular already have crafted their backend for the current way of doing things. But at least Angular should make it very easy to just swap strategies, so it uses that way across the board.

sporto commented Feb 21, 2014

@caitp I don't see how this is a silly request, serialization is a basic building block that many libraries build on top. Many time you are high in an abstraction that uses the Angular serialization underneath. So what you are proposing is not a viable option.

Also appending [] only deals with array serialization. jQuery params also makes object serialization different, see above.

Probably asking just to change this completly is an unreasonable request as people using Angular already have crafted their backend for the current way of doing things. But at least Angular should make it very easy to just swap strategies, so it uses that way across the board.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Feb 21, 2014

Contributor

Maybe the jQuery foundation should attend some IETF meetings and turn their quirk into an actual thing ;) I don't think it's a very good idea to do this just for the benefit of a handful of backends. What Angular is doing right now seems to be what is the expected behaviour.

Now, someone comes up with a configurable way to do this which works well, then that's one thing, but I just don't see this as being a very good thing to force on people.

Contributor

caitp commented Feb 21, 2014

Maybe the jQuery foundation should attend some IETF meetings and turn their quirk into an actual thing ;) I don't think it's a very good idea to do this just for the benefit of a handful of backends. What Angular is doing right now seems to be what is the expected behaviour.

Now, someone comes up with a configurable way to do this which works well, then that's one thing, but I just don't see this as being a very good thing to force on people.

@ilyagelman

This comment has been minimized.

Show comment
Hide comment
@ilyagelman

ilyagelman Sep 9, 2014

+1 please fix.
The workaround for now is to use $.param and pass it as a part of the url string.

$http.get(page + '/?' + $.param(params))

But this is an ugly solution, which also depends on jQuery.

ilyagelman commented Sep 9, 2014

+1 please fix.
The workaround for now is to use $.param and pass it as a part of the url string.

$http.get(page + '/?' + $.param(params))

But this is an ugly solution, which also depends on jQuery.

@elanperach

This comment has been minimized.

Show comment
Hide comment
@elanperach

elanperach commented Sep 9, 2014

+1

@500tech-user

This comment has been minimized.

Show comment
Hide comment
@500tech-user

500tech-user commented Sep 9, 2014

+1

@yonibot

This comment has been minimized.

Show comment
Hide comment
@yonibot

yonibot commented Sep 9, 2014

+1

@nirkaufman

This comment has been minimized.

Show comment
Hide comment
@nirkaufman

nirkaufman commented Sep 9, 2014

+1

@lgalfaso

This comment has been minimized.

Show comment
Hide comment
@lgalfaso

lgalfaso Sep 9, 2014

Member

I think it should be possible to write a small library that adds a global interceptor to $http and converts the parameters into another format. This was discussed at #7423 and the consensus was that the current serialization works well for most people and that the external module would be the solution for the cases it does not

Member

lgalfaso commented Sep 9, 2014

I think it should be possible to write a small library that adds a global interceptor to $http and converts the parameters into another format. This was discussed at #7423 and the consensus was that the current serialization works well for most people and that the external module would be the solution for the cases it does not

@timothyjlaurent

This comment has been minimized.

Show comment
Hide comment
@timothyjlaurent

timothyjlaurent commented Oct 1, 2014

Thanks @ilyagelman!

@goncalvesjoao

This comment has been minimized.

Show comment
Hide comment
@goncalvesjoao

goncalvesjoao Nov 3, 2014

+1
I can't be the only one that can't change the server's code the meet angular's pickiness so, do any of you guys know a workaround this? Even if it's an ugly one...

goncalvesjoao commented Nov 3, 2014

+1
I can't be the only one that can't change the server's code the meet angular's pickiness so, do any of you guys know a workaround this? Even if it's an ugly one...

@gabrielmaldi

This comment has been minimized.

Show comment
Hide comment
@gabrielmaldi

gabrielmaldi Nov 13, 2014

Contributor

+1

ASP.NET Web API recognizes either:

bar.baz=abc

or

bar[baz]=abc

It would be very convenient if Angular supported this out of the box.

Contributor

gabrielmaldi commented Nov 13, 2014

+1

ASP.NET Web API recognizes either:

bar.baz=abc

or

bar[baz]=abc

It would be very convenient if Angular supported this out of the box.

@gabrielmaldi

This comment has been minimized.

Show comment
Hide comment
@gabrielmaldi

gabrielmaldi Nov 13, 2014

Contributor

Here's how I'm handling it right now:

https://gist.github.com/gabrielmaldi/5453d87402db5a56c1a5

It seems very long because I included uri.js. But the key parts are queryStringParam.js (adapted from jQuery.param) and httpInterceptor.js.

Maybe it helps someone.

Contributor

gabrielmaldi commented Nov 13, 2014

Here's how I'm handling it right now:

https://gist.github.com/gabrielmaldi/5453d87402db5a56c1a5

It seems very long because I included uri.js. But the key parts are queryStringParam.js (adapted from jQuery.param) and httpInterceptor.js.

Maybe it helps someone.

@taelor

This comment has been minimized.

Show comment
Hide comment
@taelor

taelor Dec 8, 2014

I really wish there was something that could be done for all the Rails/Grape developers who are used to dealing with $.params from jquery, but are trying to move to an angular-only front-end client. I think there enough people effected by this that it would make for a stellar option if we could configure our apps to turn on this style of serialization for GET requests.

+1

taelor commented Dec 8, 2014

I really wish there was something that could be done for all the Rails/Grape developers who are used to dealing with $.params from jquery, but are trying to move to an angular-only front-end client. I think there enough people effected by this that it would make for a stellar option if we could configure our apps to turn on this style of serialization for GET requests.

+1

@pkozlowski-opensource

This comment has been minimized.

Show comment
Hide comment
@pkozlowski-opensource

pkozlowski-opensource Dec 8, 2014

Member

@taelor I know this is a pain and we are going to provide an elegant solution for this in the near future. It is in the works.

Member

pkozlowski-opensource commented Dec 8, 2014

@taelor I know this is a pain and we are going to provide an elegant solution for this in the near future. It is in the works.

@taelor

This comment has been minimized.

Show comment
Hide comment
@taelor

taelor Dec 8, 2014

@pkozlowski-opensource thanks for the super quick reply, its very reassuring!

taelor commented Dec 8, 2014

@pkozlowski-opensource thanks for the super quick reply, its very reassuring!

@jchatel

This comment has been minimized.

Show comment
Hide comment
@jchatel

jchatel Dec 9, 2014

+1

As long as the "elegant" solution doesn't come in the form of "2.X sorry we don't give a shit about 1.x", this would be fine.

But... 1.5 years this is open, super annoying and still not fixed, no one assigned, so I would not hold my breath

jchatel commented Dec 9, 2014

+1

As long as the "elegant" solution doesn't come in the form of "2.X sorry we don't give a shit about 1.x", this would be fine.

But... 1.5 years this is open, super annoying and still not fixed, no one assigned, so I would not hold my breath

@petebacondarwin petebacondarwin modified the milestones: Backlog, 1.4.x Dec 15, 2014

@danbarua

This comment has been minimized.

Show comment
Hide comment
@danbarua

danbarua Dec 18, 2014

Contributor

As long as the "elegant" solution doesn't come in the form of "2.X sorry we don't give a shit about 1.x", this would be fine.

👍

Contributor

danbarua commented Dec 18, 2014

As long as the "elegant" solution doesn't come in the form of "2.X sorry we don't give a shit about 1.x", this would be fine.

👍

@pkozlowski-opensource

This comment has been minimized.

Show comment
Hide comment
@pkozlowski-opensource

pkozlowski-opensource Dec 18, 2014

Member

A solution will be part of 1.4: http://angularjs.blogspot.fr/2014/12/planning-angular-14.html

@danbarua @jchatel I'm afraid that those snarky comments are not helpful not appreciated... If you want to contribute please comment on the actual technical solution you would propose.

Member

pkozlowski-opensource commented Dec 18, 2014

A solution will be part of 1.4: http://angularjs.blogspot.fr/2014/12/planning-angular-14.html

@danbarua @jchatel I'm afraid that those snarky comments are not helpful not appreciated... If you want to contribute please comment on the actual technical solution you would propose.

@pkozlowski-opensource pkozlowski-opensource self-assigned this Dec 18, 2014

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Dec 18, 2014

Contributor

Lets just implement jQuery param serializing, it will make people happy, I guess. We can even add a new "legacy" parameter to the http config to use jQuery's legacy serialization option, just to make the API less confusing for everyone.

Contributor

caitp commented Dec 18, 2014

Lets just implement jQuery param serializing, it will make people happy, I guess. We can even add a new "legacy" parameter to the http config to use jQuery's legacy serialization option, just to make the API less confusing for everyone.

@pkozlowski-opensource

This comment has been minimized.

Show comment
Hide comment
@pkozlowski-opensource

pkozlowski-opensource Dec 18, 2014

Member

@caitp I'm on it. There is slightly more to it as we need to make sure that people can write tests easily. Going to share a gist with a proposed solution over the weekend.

But yes, I'm working on it and it will be part of 1.4.

Member

pkozlowski-opensource commented Dec 18, 2014

@caitp I'm on it. There is slightly more to it as we need to make sure that people can write tests easily. Going to share a gist with a proposed solution over the weekend.

But yes, I'm working on it and it will be part of 1.4.

@jchatel

This comment has been minimized.

Show comment
Hide comment
@jchatel

jchatel Dec 18, 2014

I was just paraphrasing how 2.0 was announced, at least that's how I (and many others) took it.

I think there was plenty of comments already mentioning the solution: jQuery param serialisation and +1 didn't have much effect in the last 1.5 year it seemed.

jchatel commented Dec 18, 2014

I was just paraphrasing how 2.0 was announced, at least that's how I (and many others) took it.

I think there was plenty of comments already mentioning the solution: jQuery param serialisation and +1 didn't have much effect in the last 1.5 year it seemed.

@pkozlowski-opensource

This comment has been minimized.

Show comment
Hide comment
@pkozlowski-opensource

pkozlowski-opensource Dec 28, 2014

Member

For anyone interested in this issue here is the very first draft of a proposed solution for 1.4: https://gist.github.com/pkozlowski-opensource/5a57d28ccfeacaba7661 - if you care about it being solved properly please comment in the gist or in this issue directly.

Unfortunately we can't simply implement jQuery's param logic by default as:

  • it would be a breaking change (and a painful one, especially for backends like Java that understand the current serialization schema)
  • it wouldn't solve other issues opened for the same area (ex.: #3311 and #9224 that my proposal addresses).

Very open to all the constructive comments, let's get it fixed as well as we can in 1.4.

Member

pkozlowski-opensource commented Dec 28, 2014

For anyone interested in this issue here is the very first draft of a proposed solution for 1.4: https://gist.github.com/pkozlowski-opensource/5a57d28ccfeacaba7661 - if you care about it being solved properly please comment in the gist or in this issue directly.

Unfortunately we can't simply implement jQuery's param logic by default as:

  • it would be a breaking change (and a painful one, especially for backends like Java that understand the current serialization schema)
  • it wouldn't solve other issues opened for the same area (ex.: #3311 and #9224 that my proposal addresses).

Very open to all the constructive comments, let's get it fixed as well as we can in 1.4.

@odedniv

This comment has been minimized.

Show comment
Hide comment
@odedniv

odedniv Jul 5, 2015

After reading through this long thread, I still didn't get a solution. Here is a simple one:

module.run(['$http', '$httpParamSerializerJQLike', function($http, $httpParamSerializerJQLike) {
  $http.defaults.paramSerializer = $httpParamSerializerJQLike;
}]);

odedniv commented Jul 5, 2015

After reading through this long thread, I still didn't get a solution. Here is a simple one:

module.run(['$http', '$httpParamSerializerJQLike', function($http, $httpParamSerializerJQLike) {
  $http.defaults.paramSerializer = $httpParamSerializerJQLike;
}]);
@pkozlowski-opensource

This comment has been minimized.

Show comment
Hide comment
@pkozlowski-opensource

pkozlowski-opensource Jul 6, 2015

Member

(Slightly) simpler (?) / shorter way of doing the same:

module.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.paramSerializer = '$httpParamSerializerJQLike';
}]);
Member

pkozlowski-opensource commented Jul 6, 2015

(Slightly) simpler (?) / shorter way of doing the same:

module.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.paramSerializer = '$httpParamSerializerJQLike';
}]);

netman92 added a commit to netman92/angular.js that referenced this issue Aug 8, 2015

@armanforghani

This comment has been minimized.

Show comment
Hide comment
@armanforghani

armanforghani Oct 23, 2015

@pkozlowski-opensource
$httpProvider.defaults.paramSerializer = '$httpParamSerializerJQLike'; does not work using Angular 1.4.6.

armanforghani commented Oct 23, 2015

@pkozlowski-opensource
$httpProvider.defaults.paramSerializer = '$httpParamSerializerJQLike'; does not work using Angular 1.4.6.

@xuwupeng2000

This comment has been minimized.

Show comment
Hide comment
@xuwupeng2000

xuwupeng2000 commented Mar 17, 2016

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment