Change ContentType or CharacterEncoding in Java Filter ONLY IF ContentType === JSON
content-type, filter, java, jersey-2.0
Solution
Thanks to the other answers on this page, I found a way to do it.... Very close to what they were suggesting, but it turned out the only way I could get it to work was to override "getOutputStream" and look at the contentType at that point. I've put this filter as the first filter in the chain, and it seems to work fine.
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.ws.rs.core.MediaType;
public class EnsureJsonIsUtf8ResponseFilter implements Filter
{
final String APPLICATION_JSON_WITH_UTF8_CHARSET = MediaType.APPLICATION_JSON + ";charset=" + java.nio.charset.StandardCharsets.UTF_8;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
HttpServletResponse r = (HttpServletResponse) response;
HttpServletResponse wrappedResponse = new HttpServletResponseWrapper(r)
{
@Override
public ServletOutputStream getOutputStream() throws java.io.IOException
{
ServletResponse response = this.getResponse();
String ct = (response != null) ? response.getContentType() : null;
if (ct != null && ct.toLowerCase().startsWith(MediaType.APPLICATION_JSON))
{
response.setContentType(APPLICATION_JSON_WITH_UTF8_CHARSET);
}
return super.getOutputStream();
}
};
chain.doFilter(request, wrappedResponse);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
// This method intentionally left blank
}
@Override
public void destroy()
{
// This method intentionally left blank
}
}
Problem
I'm trying to ensure that all JSON responses from a Jersey based java application have a UTF-8 character encoding parameter appended to their ContentType header. So if it's a JSON response, I would like the response header for the `Content-Type` to be Content-Type: application/json;charset=UTF-8 `EDIT: I know I can do this on a case by case basis, but I'd like to do it globally, so it affects all content responses that have a content type of "application/json". ` If I just try and set the character encoding in my filter regardless of the content type, it works fine. But I only want to set the character encoding if the ContentType is "application/json". I find that the response.getContentType() method always returns null unless I call chain.doFilter first. But if I try and change the Character Encoding after this, it seems to always get overwritten. ``` import java.io.IOException; import javax.servlet.*; import javax.servlet.http.*; import javax.ws.rs.core.MediaType; public class EnsureJsonResponseIsUtf8Filter implements Filter { private class SimpleWrapper extends HttpServletResponseWrapper { public SimpleWrapper(HttpServletResponse response) { super(response); } @Override public String getCharacterEncoding() { return "UTF-8"; } } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); if (response.getContentType() != null && response.getContentType().contains(MediaType.APPLICATION_JSON)) { response.setCharacterEncoding("UTF-8"); chain.doFilter(request, new SimpleWrapper((HttpServletResponse) response)); } } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } } ``` I've seen other similar questions, but none them seem to have this issue. I've tried registering my filter as the first, and last filter with no luck.
Related problems
- Looking for an example for inserting content into the response using a servlet filter
- jersey web service json utf-8 encoding
- How to add response headers based on Content-type; getting Content-type before the response is committed
- Differences between ServletResponse and HttpServletResponseWrapper?
- How to override response header in jersey client