152
152
* @see org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
153
153
* @see org.springframework.util.MultiValueMap
154
154
*/
155
- public class FormHttpMessageConverter implements HttpMessageConverter <Map <String , ?>> {
155
+ public class FormHttpMessageConverter implements HttpMessageConverter <MultiValueMap <String , ?>> {
156
156
157
157
/** The default charset used by the converter. */
158
158
public static final Charset DEFAULT_CHARSET = StandardCharsets .UTF_8 ;
@@ -295,7 +295,7 @@ public void setMultipartCharset(Charset charset) {
295
295
296
296
@ Override
297
297
public boolean canRead (Class <?> clazz , @ Nullable MediaType mediaType ) {
298
- if (!Map .class .isAssignableFrom (clazz )) {
298
+ if (!MultiValueMap .class .isAssignableFrom (clazz )) {
299
299
return false ;
300
300
}
301
301
if (mediaType == null ) {
@@ -330,7 +330,7 @@ public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
330
330
}
331
331
332
332
@ Override
333
- public Map <String , ? > read (@ Nullable Class <? extends Map <String , ?>> clazz ,
333
+ public MultiValueMap <String , String > read (@ Nullable Class <? extends MultiValueMap <String , ?>> clazz ,
334
334
HttpInputMessage inputMessage ) throws IOException , HttpMessageNotReadableException {
335
335
336
336
MediaType contentType = inputMessage .getHeaders ().getContentType ();
@@ -339,76 +339,41 @@ public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
339
339
String body = StreamUtils .copyToString (inputMessage .getBody (), charset );
340
340
341
341
String [] pairs = StringUtils .tokenizeToStringArray (body , "&" );
342
- Map <String , String > svResult = null ;
343
- MultiValueMap <String , String > mvResult = null ;
344
- if (clazz == null || MultiValueMap .class .isAssignableFrom (clazz )) {
345
- mvResult = new LinkedMultiValueMap <>(pairs .length );
346
- }
347
- else {
348
- svResult = CollectionUtils .newLinkedHashMap (pairs .length );
349
- }
342
+ MultiValueMap <String , String > result = new LinkedMultiValueMap <>(pairs .length );
350
343
for (String pair : pairs ) {
351
344
int idx = pair .indexOf ('=' );
352
345
if (idx == -1 ) {
353
- String name = URLDecoder .decode (pair , charset );
354
- if (mvResult != null ) {
355
- mvResult .add (name , null );
356
- }
357
- else if (svResult != null ) {
358
- svResult .put (name , null );
359
- }
346
+ result .add (URLDecoder .decode (pair , charset ), null );
360
347
}
361
348
else {
362
349
String name = URLDecoder .decode (pair .substring (0 , idx ), charset );
363
350
String value = URLDecoder .decode (pair .substring (idx + 1 ), charset );
364
- if (mvResult != null ) {
365
- mvResult .add (name , value );
366
- }
367
- else if (svResult != null ) {
368
- svResult .put (name , value );
369
- }
351
+ result .add (name , value );
370
352
}
371
353
}
372
- if (mvResult != null ) {
373
- return mvResult ;
374
- }
375
- else if (svResult != null ) {
376
- return svResult ;
377
- }
378
- else {
379
- throw new IllegalStateException ();
380
- }
354
+ return result ;
381
355
}
382
356
383
357
@ Override
384
358
@ SuppressWarnings ("unchecked" )
385
- public void write (Map <String , ?> map , @ Nullable MediaType contentType , HttpOutputMessage outputMessage )
359
+ public void write (MultiValueMap <String , ?> map , @ Nullable MediaType contentType , HttpOutputMessage outputMessage )
386
360
throws IOException , HttpMessageNotWritableException {
387
361
388
362
if (isMultipart (map , contentType )) {
389
- writeMultipart ((Map <String , Object >) map , contentType , outputMessage );
363
+ writeMultipart ((MultiValueMap <String , Object >) map , contentType , outputMessage );
390
364
}
391
365
else {
392
- writeForm ((Map <String , Object >) map , contentType , outputMessage );
366
+ writeForm ((MultiValueMap <String , Object >) map , contentType , outputMessage );
393
367
}
394
368
}
395
369
396
370
397
- private boolean isMultipart (Map <String , ?> map , @ Nullable MediaType contentType ) {
371
+ private boolean isMultipart (MultiValueMap <String , ?> map , @ Nullable MediaType contentType ) {
398
372
if (contentType != null ) {
399
373
return contentType .getType ().equalsIgnoreCase ("multipart" );
400
374
}
401
- if (map instanceof MultiValueMap <?, ?> mvMap ) {
402
- for (List <?> values : mvMap .values ()) {
403
- for (Object value : values ) {
404
- if (value != null && !(value instanceof String )) {
405
- return true ;
406
- }
407
- }
408
- }
409
- }
410
- else {
411
- for (Object value : map .values ()) {
375
+ for (List <?> values : map .values ()) {
376
+ for (Object value : values ) {
412
377
if (value != null && !(value instanceof String )) {
413
378
return true ;
414
379
}
@@ -417,7 +382,7 @@ private boolean isMultipart(Map<String, ?> map, @Nullable MediaType contentType)
417
382
return false ;
418
383
}
419
384
420
- private void writeForm (Map <String , Object > formData , @ Nullable MediaType mediaType ,
385
+ private void writeForm (MultiValueMap <String , Object > formData , @ Nullable MediaType mediaType ,
421
386
HttpOutputMessage outputMessage ) throws IOException {
422
387
423
388
mediaType = getFormContentType (mediaType );
@@ -465,37 +430,30 @@ protected MediaType getFormContentType(@Nullable MediaType contentType) {
465
430
return contentType ;
466
431
}
467
432
468
- protected String serializeForm (Map <String , Object > formData , Charset charset ) {
433
+ protected String serializeForm (MultiValueMap <String , Object > formData , Charset charset ) {
469
434
StringBuilder builder = new StringBuilder ();
470
- formData .forEach ((name , value ) -> {
435
+ formData .forEach ((name , values ) -> {
471
436
if (name == null ) {
472
- Assert .isTrue (value == null || value instanceof List <?> values && values .isEmpty (),
473
- () -> "Null name in form data: " + formData );
437
+ Assert .isTrue (CollectionUtils .isEmpty (values ), () -> "Null name in form data: " + formData );
474
438
return ;
475
439
}
476
- if (value instanceof List <?> values ) {
477
- values .forEach (v -> serializeFormValue (name , value , charset , builder ));
478
- }
479
- else {
480
- serializeFormValue (name , value , charset , builder );
481
- }
440
+ values .forEach (value -> {
441
+ if (builder .length () != 0 ) {
442
+ builder .append ('&' );
443
+ }
444
+ builder .append (URLEncoder .encode (name , charset ));
445
+ if (value != null ) {
446
+ builder .append ('=' );
447
+ builder .append (URLEncoder .encode (String .valueOf (value ), charset ));
448
+ }
449
+ });
482
450
});
483
- return builder .toString ();
484
- }
485
451
486
- private static void serializeFormValue (String name , @ Nullable Object value , Charset charset , StringBuilder builder ) {
487
- if (!builder .isEmpty ()) {
488
- builder .append ('&' );
489
- }
490
- builder .append (URLEncoder .encode (name , charset ));
491
- if (value != null ) {
492
- builder .append ('=' );
493
- builder .append (URLEncoder .encode (String .valueOf (value ), charset ));
494
- }
452
+ return builder .toString ();
495
453
}
496
454
497
455
private void writeMultipart (
498
- Map <String , Object > parts , @ Nullable MediaType contentType , HttpOutputMessage outputMessage )
456
+ MultiValueMap <String , Object > parts , @ Nullable MediaType contentType , HttpOutputMessage outputMessage )
499
457
throws IOException {
500
458
501
459
// If the supplied content type is null, fall back to multipart/form-data.
@@ -542,23 +500,13 @@ private boolean isFilenameCharsetSet() {
542
500
return (this .multipartCharset != null );
543
501
}
544
502
545
- private void writeParts (OutputStream os , Map <String , Object > parts , byte [] boundary ) throws IOException {
546
- for (Map .Entry <String , Object > entry : parts .entrySet ()) {
503
+ private void writeParts (OutputStream os , MultiValueMap <String , Object > parts , byte [] boundary ) throws IOException {
504
+ for (Map .Entry <String , List < Object > > entry : parts .entrySet ()) {
547
505
String name = entry .getKey ();
548
- Object value = entry .getValue ();
549
- if (value instanceof List <?> values ) {
550
- for (Object part : values ) {
551
- if (part != null ) {
552
- writeBoundary (os , boundary );
553
- writePart (name , getHttpEntity (part ), os );
554
- writeNewLine (os );
555
- }
556
- }
557
- }
558
- else {
559
- if (value != null ) {
506
+ for (Object part : entry .getValue ()) {
507
+ if (part != null ) {
560
508
writeBoundary (os , boundary );
561
- writePart (name , getHttpEntity (value ), os );
509
+ writePart (name , getHttpEntity (part ), os );
562
510
writeNewLine (os );
563
511
}
564
512
}
0 commit comments