Use UTF-8 with JSON in MockHttpServletResponse

This commit makes MockHttpServletResponse consistent with the other
parts of the framework where the body of a response is read as an UTF-8
String when the content type is application/json or similar, overriding
the ISO-8859-1 default Servlet encoding.

Closes gh-33019
This commit is contained in:
Sébastien Deleuze 2024-06-13 16:02:28 +02:00
parent 2116d71d81
commit 1d363e5a41
5 changed files with 21 additions and 10 deletions

View File

@ -24,6 +24,7 @@ import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@ -72,6 +73,8 @@ public class MockHttpServletResponse implements HttpServletResponse {
private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
private static final MediaType APPLICATION_PLUS_JSON = new MediaType("application", "*+json");
//---------------------------------------------------------------------
// ServletResponse properties
@ -348,6 +351,10 @@ public class MockHttpServletResponse implements HttpServletResponse {
if (mediaType.getCharset() != null) {
setExplicitCharacterEncoding(mediaType.getCharset().name());
}
else if (mediaType.isCompatibleWith(MediaType.APPLICATION_JSON) ||
mediaType.isCompatibleWith(APPLICATION_PLUS_JSON)) {
this.characterEncoding = StandardCharsets.UTF_8.name();
}
}
catch (Exception ex) {
// Try to get charset value anyway

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -257,7 +257,7 @@ public class ContentResultMatchers {
*/
public ResultMatcher json(String jsonContent, JsonComparator comparator) {
return result -> {
String content = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
String content = result.getResponse().getContentAsString();
comparator.assertIsMatch(jsonContent, content);
};
}

View File

@ -17,7 +17,6 @@
package org.springframework.test.web.servlet.result;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import com.jayway.jsonpath.JsonPath;
import org.hamcrest.Matcher;
@ -238,7 +237,7 @@ public class JsonPathResultMatchers {
}
private String getContent(MvcResult result) throws UnsupportedEncodingException {
String content = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
String content = result.getResponse().getContentAsString();
if (StringUtils.hasLength(this.prefix)) {
try {
String reason = String.format("Expected a JSON payload prefixed with \"%s\" but found: %s",

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,6 @@
package org.springframework.test.web.servlet.result;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
@ -28,7 +27,6 @@ import jakarta.servlet.http.HttpSession;
import org.springframework.core.style.ToStringCreator;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@ -250,9 +248,7 @@ public class PrintingResultHandler implements ResultHandler {
this.printer.printValue("Error message", response.getErrorMessage());
this.printer.printValue("Headers", getResponseHeaders(response));
this.printer.printValue("Content type", response.getContentType());
String body = (MediaType.APPLICATION_JSON_VALUE.equals(response.getContentType()) ?
response.getContentAsString(StandardCharsets.UTF_8) : response.getContentAsString());
this.printer.printValue("Body", body);
this.printer.printValue("Body", response.getContentAsString());
this.printer.printValue("Forwarded URL", response.getForwardedUrl());
this.printer.printValue("Redirected URL", response.getRedirectedUrl());
printCookies(response.getCookies());

View File

@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.http.MediaType;
import org.springframework.web.util.WebUtils;
import static org.assertj.core.api.Assertions.assertThat;
@ -620,4 +621,12 @@ class MockHttpServletResponseTests {
assertThat(contentTypeHeader).isEqualTo("text/plain");
}
@Test // gh-33019
void contentAsStringEncodingWithJson() throws IOException {
String content = "{\"name\": \"Jürgen\"}";
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.getWriter().write(content);
assertThat(response.getContentAsString()).isEqualTo(content);
}
}