How can I set the charset with JAX-RS? I've tried @Produces("text/html; charset=UTF-8")
but that was ignored and only text/html
was send with the HTTP header. I want to set the charset within a MessageBodyWriter, but don't want to extract the media type by analysing the @Produces annotation via reflection by myself.

- 89,107
- 111
- 320
- 448
-
12`@Produces("text/html; charset=UTF-8")` works with current versions of the reference implementation Jersey. – deamon Oct 27 '11 at 15:21
-
2You can also ensure this happens everywhere for all @Produces("text/html") annotations using the technique [described here on a similar SO question](http://stackoverflow.com/a/23479647/26510). – Brad Parks May 05 '14 at 18:57
7 Answers
As Daemon pointed out in a comment, the latest versions of JAX-RS (including the stable version as of September 2012) now do support the @Produces
syntax. So you can just use:
@Produces("text/html; charset=UTF-8")

- 16,629
- 6
- 56
- 82
-
4@Drewch Does JAX-RS 1.1 support this? Can't seem to find when JAX-RS came out. I tried `@Produces(MediaType.APPLICATION_JSON + "; charset=UTF-16")`, but that didn't work. – Luke Sep 10 '13 at 16:55
-
3@Produces("text/html; charset=UTF-8") didn't work for me in Jersey 2.13. Had the same problem described by @deamon. – André Willik Valenti Dec 05 '14 at 14:27
-
1
-
-
I confirm that it works like a charm with Jetty 9.4.31 and Jersey 2.31 – gouessej Aug 07 '20 at 23:06
Just to keep it up to date. Not sure whether this was supported in older versions of Jersey, but definitely if you decide to use ResponseBuilder.header(...) method you can use MediaType method withCharset(). Like this:
return Response.status(Status.OK)
.entity(result)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_TYPE.withCharset("utf-8"))
.build());

- 888
- 8
- 23
-
3Even shorter (and with better type safety): use `javax.ws.rs.core.Response.ResponseBuilder.type(MediaType)` instead of `javax.ws.rs.core.Response.ResponseBuilder.header(HttpHeaders.CONTENT_TYPE, Object)` – slartidan May 19 '16 at 13:17
It is also possible to use ResponseBuilder.header(...) method to set the content type with the charset. See below for a code sample (using JAX-RS 1.1.1, CXF 2.3.1).
final Response myResponse = Response.status(Response.Status.BAD_REQUEST)
.entity("La requête n'est pas correcte.\n ...")
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN+"; charset=ISO-8859-15" )
.build();

- 151
- 1
- 2
-
5you no need to set it via header, there is also `type()` method: `Response.status(Response.Status.BAR_REQUEST).entity("La requête n'est pas correcte.\n ...").type(MediaType.TEXT_PLAIN + "; charset=ISO-8859-15").build();` – To Kra Jan 27 '16 at 14:08
If you want to do this in a JAX-RS implementation neutral way, you may be able to reset the Content-Type in the MessageBodyWriter. Something like:
public void writeTo(Object obj,
Class<?> cls,
Type type,
Annotation[] annotations,
MediaType mt,
MultivaluedMap<String, Object> responseHttpHeaders,
OutputStream stream) throws IOException {
responseHttpHeaders.putSingle(javax.ws.rs.core.HttpHeaders.CONTENT_TYPE, mt.toString() + ";charset=UTF-8");
}
If you have different character sets besides UTF-8 per resource method, you may want to create a custom annotation and add it to each resource method. Then, try to use the annotations parameter in the writeTo() method.
Just FYI, Apache Wink supports the usage of charset and other attributes on media types. I hope that future JAX-RS spec revisions makes this easier.

- 2,448
- 21
- 22
First setup @Produces
annotation on your resource class methods.
Then in MessageBodyWriter
of your returned type, you can do this in writeTo()
method:
response.setContentType(mediaType.toString);
Remark: You can inject response
in your writer
by:
@Context
protected HttpServletResponse response;

- 3,344
- 3
- 38
- 45
What I do is to get an instance of the servlet response object:
protected @Context HttpServletResponse response;
And then set the character encoding to utf-8:
response.setCharacterEncoding("utf-8");
That works for me.

- 91
- 1
- 1
-
That's the same answer as [To Kra's](http://stackoverflow.com/a/39097649/1314743). Please only add an answer if you have something new to contribute. – Martin Nyolt Aug 24 '16 at 13:29
-
No, it isn't the same. Giannis uses 'setCharacterEncoding', whereas To Kra uses a roundabout method is writoTo() of MessageBodyWriter. Giannis is much simpler. – Matthew Oakley Nov 19 '16 at 05:05
If using RESTEasy you can register an Inteceptor:
import org.jboss.resteasy.annotations.interception.ServerInterceptor;
import org.jboss.resteasy.core.ResourceMethodInvoker;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
@Provider
@ServerInterceptor
public class ContentTypeSetter implements PreProcessInterceptor {
@Override
public ServerResponse preProcess(HttpRequest request, ResourceMethodInvoker resourceMethodInvoker) throws Failure, WebApplicationException {
request.setAttribute(InputPart.DEFAULT_CONTENT_TYPE_PROPERTY, "*/*; charset=UTF-8");
return null;
}
}
Note: If you manually set a @Produces it overrides the ContentType set by this interceptor. If you do that, set the charset in @Produces

- 13,504
- 9
- 62
- 95