当你想在你的代码中找到一个错误时,这很难;当你认为你的代码是不会有错误时,这就更难了。

android-Jersey Rest默认字符编码

admin 6℃
当返回JSON时,Jersey似乎失败了…
这:

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

需要返回JSON utf-8编码。如果我只用

@Produces( MediaType.APPLICATION_JSON)

如果失败,例如德语(üää),将以错误的方式返回。

两个问题:
1-对于JSON utf-8 ist标准-为什么不使用Jersey?
2-如果JSON请求传入,我可以为整个REST Servlet设置utf-8吗?

我在Android上使用Jersey 1.5和CRest 1.0.1

SRGs的建议很有魅力。但是,由于Jersey 2.0的接口略有不同,因此我们不得不稍微调整一下过滤器:

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);
            }
        }
    }
}

我也有同样的问题:我不喜欢在'@Produces'标签中到处添加字符集

我在这里找到了解决方案:http://stephen.genoprime.com/2011/05/29/jersey-charset-in-content-type.html

基本上,您只需添加一个将添加字符集的响应过滤器(例如,如果当前返回的内容类型是文本、xml或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;
    }
}

注册过滤器:

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

当然,也可以使用Guice,例如在扩展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);

SRGs和马丁斯的解决方案对我很有效

但是,我必须对过滤器应用以下更改:

如果客户端使用Accept头执行请求,Jersey会向内容类型添加一个质量因子。如下所示:

没有问题:没有接受头的请求:

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

response.getMediaType().toString()application/json . 我们可以简单地附加 ;charset=utf-8 是的

问题:带有接受头的请求:

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

response.getMediaType().toString(){application/json, q=1000} . 我们不能简单地附加 ;charset=utf-8 ,因为这将导致以下异常:

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

我建议使用以下代码来解决此问题:

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);
            }
        }
    }
}

转载请注明:我的代码 » android-Jersey Rest默认字符编码