PerlDancer / Dancer2

Perl Dancer Next Generation (rewrite of Perl Dancer)
http://perldancer.org/
Other
549 stars 274 forks source link

Some JSON requests are modified by Hash::MultiValue #1240

Open bjornwein opened 8 years ago

bjornwein commented 8 years ago

I noticed that for some JSON body parameter schemas, arrays are sometimes simply removed when deserialized and stored in request->body_request() For example, this JSON body parameter:

{
  "foo": [ { "bar": 1 } ],
  "baz": { "foobar": [ { "blah": 2 } ] }
}

will be parsed into this in a route:

$VAR1 = {
          'foo' => {
                     'bar' => 1
                   }
          'baz' => {
                     'foobar' => [
                                   {
                                     'blah' => 2
                                   }
                                 ]
                   },
        };

Notice that the "foo" field is no longer an array after the deserialization, but the "foobar" field is as expected. I can reproduce this in both 0.202000 and 0.203000.

I tracked it down to the use of Hash::MultiValue->from_mixed(), and with this naive patch it works as expected for me:

--- Dancer2/Core/Request.pm.orig    2016-09-02 11:05:27.042773871 +0200
+++ Dancer2/Core/Request.pm 2016-09-02 11:05:35.714634529 +0200
@@ -213,8 +213,8 @@

     # Set body parameters (HMV)
     # Not happy with fiddling with Plack::Request internals -- veryrusty Aug 2016.
     $self->env->{'plack.request.body'} =
-        Hash::MultiValue->from_mixed( ref $data eq 'HASH' ? %$data : () );
+        Hash::MultiValue->new( ref $data eq 'HASH' ? %$data : () );

     return $data;
 }

I expect my "solution" to break more than it fixes, but I hope that you experts can come up with a better solution.

SysPete commented 8 years ago

@bjornax many thanks for creating the issue. PR on its way.

SysPete commented 8 years ago

Converting JSON (and other serialized data) to HMV seems like a bad move: https://github.com/miyagawa/Hash-MultiValue/issues/11

@bjornax I'd suggest as a workaround until we've got this nailed down is to NOT use body_parameters but grab your data using the good old params keyword:

my $data = from_json(params('body'));
bjornwein commented 8 years ago

@SysPete ok. Thank you for the impressively quick initial response. A temporary workaround is no problem for me as I'm still prototyping. Looking forward to a permanent solution when ready.