2011-04-01 12 views
16

Jersey parece fallar al volver JSON ...
Este:Jersey/Resto de caracteres por defecto de codificación

@GET 
@Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8") 
public List<MyObject> getMyObjects() { 
    return ....; 
} 

se necesita para volver JSON codificación UTF-8. Si yo sólo uso

@Produces(MediaType.APPLICATION_JSON) 

falla y, por ejemplo Umlaute Alemán (uoa), será devuelto en un camino equivocado.

dos preguntas:
1 - Para JSON UTF-8 estándar ist - por qué no con Jersey?
2 - ¿Puedo configurar utf-8 para todo el servlet REST si entra una solicitud JSON?

estoy usando Jersey 1.5 y 1.0.1 de la cresta en Android ...

+0

Cómo se volvieron? ¿Puedes mostrar algún resultado de muestra? –

+0

Devuelve Löwe en lugar de Löwe (Lion en inglés) pero como dije si uso @Produces (MediaType.APPLICATION_JSON + "; charset = UTF-8") funciona ... –

+0

Soy realmente el único que tiene ¿este problema? –

Respuesta

6

que tenían el mismo problema: no me gusta añadir el juego de caracteres en la etiqueta "@Produces" en todas partes.

he encontrado la solución aquí: http://stephen.genoprime.com/2011/05/29/jersey-charset-in-content-type.html

Básicamente, sólo hay que añadir un filtro de respuesta que va a añadir el juego de caracteres (por ejemplo, si el tipo de contenido actualmente devueltas es de 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"); 

también funciona con Guice, por supuesto, por ejemplo en su clase que se extiende Servl etModule:

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); 
+0

La fuente completa y más detallada de cómo implementar esto [se puede encontrar aquí] (https://github.com/tinkerpop/rexster/blob/master/rexster-server/src/main/java/com/tinkerpop/rexster /filter/HeaderResponseFilter.java), y permite el caso en el que un método ya ha configurado el "Tipo de contenido", lo que permite anulaciones cuando sea necesario. –

15

La sugerencia de SRG funciona a las mil maravillas. Sin embargo, desde Jersey 2.0 las interfaces son ligeramente diferentes, así 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); 
      } 
     } 
    } 
} 
+1

¡Gracias por la actualización! Empecé con el uso de Jersey y tropecé con este problema, ¡tu solución funcionó perfectamente! Nota para los usuarios de Grizzly: Para registrar este filtro, simplemente necesita llamar 'rc.register (com.example.CharsetResponseFilter.class);' en su método de inicio (estoy usando el código repetitivo generado del tutorial). – DHainzl

3

grupos autónomos y Martins solución funcionó bien para mí.

Sin embargo, he tenido que aplicar los siguientes cambios en el filtro:

Si el cliente hace un pedido con una cabecera Accept, Jersey añade un factor de calidad para el tipo de contenido. Esto se ve de la siguiente manera:

No hay problema: solicitud sin cabecera Accept:

curl -i http://www.example.com/my-rest-endpoint

response.getMediaType().toString() es application/json. Simplemente podemos agregar ;charset=utf-8.

Problema: solicitud con cabecera Accept:

curl -i -H "Accept: application/json" http://www.example.com/my-rest-endpoint

response.getMediaType().toString() es {application/json, q=1000}.No podemos simplemente añadir ;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 

me gustaría sugerir 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); 
      } 
     } 
    } 
} 
Cuestiones relacionadas