android - type - Codificación de caracteres por defecto de Jersey/Rest
meta content type application json (3)
La solución de SRGs y martins funcionó bien para mí.
Sin embargo, tuve que aplicar los siguientes cambios al filtro:
Si el cliente realiza una solicitud con un encabezado Aceptar, Jersey agrega un factor de calidad al tipo de contenido. Esto se ve como sigue:
No hay problema: solicitud sin aceptar encabezado:
curl -i http://www.example.com/my-rest-endpoint
response.getMediaType().toString()
es application/json
. Simplemente podemos adjuntar ;charset=utf-8
.
Problema: solicitud con cabecera Aceptar:
curl -i -H "Accept: application/json" http://www.example.com/my-rest-endpoint
response.getMediaType().toString()
es {application/json, q=1000}
. No podemos simplemente agregar ;charset=utf-8
, ya que esto llevaría a la siguiente excepción:
java.lang.IllegalArgumentException: Error parsing media type ''{application/json, q=1000};charset=utf-8''
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:92) ~[na:na]
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:60) ~[na:na]
at javax.ws.rs.core.MediaType.valueOf(MediaType.java:179) ~[na:na]
...
Caused by: java.text.ParseException: Next event is not a Token
at org.glassfish.jersey.message.internal.HttpHeaderReader.nextToken(HttpHeaderReader.java:129) ~[na:na]
at org.glassfish.jersey.message.internal.MediaTypeProvider.valueOf(MediaTypeProvider.java:110) ~[na:na]
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:90) ~[na:na]
... 193 common frames omitted
Sugeriría el siguiente código para resolver este problema:
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.MediaType;
public class CharsetResponseFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext request, ContainerResponseContext response) {
MediaType type = response.getMediaType();
if (type != null) {
if (!type.getParameters().containsKey(MediaType.CHARSET_PARAMETER)) {
MediaType typeWithCharset = type.withCharset("utf-8");
response.getHeaders().putSingle("Content-Type", typeWithCharset);
}
}
}
}
Jersey parece fallar al devolver JSON ...
Esta:
@GET
@Produces( MediaType.APPLICATION_JSON + ";charset=UTF-8")
public List<MyObject> getMyObjects() {
return ....;
}
Es necesario para devolver JSON utf-8 codificado. Si uso solo
@Produces( MediaType.APPLICATION_JSON)
falla y, por ejemplo, umlaute alemán (üöä), se devolverá de forma incorrecta.
Dos preguntas:
1 - Para JSON utf-8 es el estándar, ¿por qué no con Jersey?
2 - ¿Puedo configurar utf-8 para todo REST-Servlet si llega una solicitud JSON?
Estoy usando Jersey 1.5 y CRest 1.0.1 en Android ...
La sugerencia de SRG funciona como un encanto. Sin embargo, desde Jersey 2.0 las interfaces son ligeramente diferentes, por lo que tuvimos que adaptar el filtro un poco:
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.MediaType;
public class CharsetResponseFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext request, ContainerResponseContext response) {
MediaType type = response.getMediaType();
if (type != null) {
String contentType = type.toString();
if (!contentType.contains("charset")) {
contentType = contentType + ";charset=utf-8";
response.getHeaders().putSingle("Content-Type", contentType);
}
}
}
}
Tuve el mismo problema: no me gusta agregar el conjunto de caracteres en la etiqueta "@Produces" en todas partes.
Encontré la solución aquí: http://stephen.genoprime.com/2011/05/29/jersey-charset-in-content-type.html
Básicamente, solo tiene que agregar un filtro de respuesta que agregará el conjunto de caracteres (por ejemplo, si el tipo de contenido que se devuelve actualmente es texto, xml o json)
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerResponse;
import com.sun.jersey.spi.container.ContainerResponseFilter;
import javax.ws.rs.core.MediaType;
public class CharsetResponseFilter implements ContainerResponseFilter {
public ContainerResponse filter(ContainerRequest request, ContainerResponse response) {
MediaType contentType = response.getMediaType();
response.getHttpHeaders().putSingle("Content-Type", contentType.toString() + ";charset=UTF-8");
return response;
}
}
Y para registrar el filtro:
ServletAdapter jerseyAdapter = new ServletAdapter();
jerseyAdapter.addInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters", "com.my.package.MyResponseFilter");
Por supuesto, también funciona con Guice, por ejemplo, en su clase, extendiendo ServletModule:
final Map<String, String> parameters = new HashMap<String, String>();
parameters.put("com.sun.jersey.spi.container.ContainerResponseFilters", com.package.JerseyCharsetResponseFilter.class.getName());
serve("/*").with(GuiceContainer.class, parameters);