Jersey / Rest default character encoding

前端 未结 3 1041
伪装坚强ぢ
伪装坚强ぢ 2020-12-16 14:15

Jersey seems to fail when returning JSON...
This:

@GET
@Produces( MediaType.APPLICATION_JSON + \";charset=UTF-8\")
public List getMyObje         


        
相关标签:
3条回答
  • 2020-12-16 14:30

    SRGs suggestion works like a charm. However, since Jersey 2.0 the interfaces are slightly different, so we had to adapt the filter a little bit:

    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);
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-16 14:30

    SRGs and martins solution worked well for me.

    However, I had to apply the following changes to the filter:

    If the client does a request with an Accept header, Jersey adds a quality factor to the content type. This looks as follows:

    No problem: request without Accept header:

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

    response.getMediaType().toString() is application/json. We can simply append ;charset=utf-8.

    Problem: request with Accept header:

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

    response.getMediaType().toString() is {application/json, q=1000}. We cannot simply append ;charset=utf-8, since this would lead to the following exception:

    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
    

    I'd suggest the following code to solve this problem:

    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);
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-16 14:44

    I had the same problem : i don't like adding the charset in the "@Produces" tag everywhere.

    I found the solution right here : http://stephen.genoprime.com/2011/05/29/jersey-charset-in-content-type.html

    Basically, you just have to add a response filter that will add the charset (for example if the content type currently returned is either text, xml or 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;
        }
    }
    

    And to register the filter :

    ServletAdapter jerseyAdapter = new ServletAdapter();
    jerseyAdapter.addInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters", "com.my.package.MyResponseFilter"); 
    

    Works too with Guice, of course, for example in your class extending 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);
    
    0 讨论(0)
提交回复
热议问题