来自 REST 查询的 UTF-8 编码字符未正确呈现

UTF-8 encoded characters from REST-query not rendered properly

我正在使用一个外部 REST 服务,该服务以 UTF-8 编码提供所有内容。

出于某种原因,我的应用程序无法正确处理响应。如果我转储响应,我会选择 LuleÃ¥(应该是 Luleå)之类的东西。

编辑: 如果我将字符串转发(不更改)到 UI,则会发生相同的行为,例如:

flash.message = "Test" + integrationService.testEncoding()

我所做的是在 /script 文件夹中创建一个 _Events.groovy 文件并在其中指定

eventConfigureTomcat = { tomcat ->
    tomcat.connector.URIEncoding = "UTF-8"
    tomcat.connector.useBodyEncodingForURI = true
}

我的 Config.groovy 中还有以下内容:

grails.views.gsp.encoding = "UTF-8"
grails.converters.encoding = "UTF-8"

但这并没有改变什么。响应仍然显示错误。我不确定这是否是 Grails、嵌入式 tomcat 或其他东西的配置问题。我目前 运行 我在 windows 7 上的测试设置,但同样的问题发生在我的 Centos 服务器 运行 上。请指教

编辑2: 如果我使用 curl 使用 REST 服务,输出中的所有内容都会正确呈现。

编辑3: 我正在使用 org.springframework.web.client.RestTemplateHttpComponents 来使用服务:

private static final HttpHeaders requestHeaders
static{
    requestHeaders = new HttpHeaders()
    requestHeaders.set(HttpHeaders.CONTENT_TYPE, "application/json")
    requestHeaders.set(HttpHeaders.ACCEPT, "application/json")
    requestHeaders.set("Accept-Encoding", "gzip")
}

private final static RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory(
    HttpClientBuilder.create().build()))
...
...
public def testEncoding(){
    ResponseEntity<String> response = restTemplate.exchange(
            "https://www.url.com", HttpMethod.GET, new HttpEntity<Object>(requestHeaders),
            String.class)
    def gamesJson = JSON.parse(response.getBody())
    //...
    //parse value from gamesJson
    //...
    return testValue
}

可以在环境本身中强制执行编码类型。

JAVA_TOOL_OPTIONS -Dfile.encoding=UTF8 -Dclient.encoding.override=UTF-8

只需尝试在 windows/linux 中设置上述编码设置。我希望这可以解决问题。

在这种情况下,JVM 将从环境变量中获取默认编码类型。

我们的团队之前遇到过类似的问题,我们有一个第三方服务,他们说他们的输出是用 UTF-8 编码的。但是返回的字符串还是乱码。经过一些测试后,结果发现他们返回的是 ISO-8859-1 编码的字符串。我们所做的是 decode/encode 将他们的输入转换为 UTF-8 编码字符,以便我们可以正确使用它们。

对于你的情况,我认为这是一个类似的问题:

UTF-8: Luleå

ISO-8859-1: Luleå

在Java中,我们做了这样的事情:

Charset initialEncoding = Charsets.ISO_8859_1;
Charset outputEncoding = Charsets.UTF_8; 
byte[] byteArray = input.getBytes(initialEncoding);
String output = new String(new String(byteArray, outputEncoding));

在 Groovy 中,我认为你可以做类似

的事情
import groovy.json.JsonSlurper;

def main = {
    def response = '{"name":"Luleå"}' 

    def slurper = new JsonSlurper()
    def result = slurper.parse(response.getBytes(), 'UTF-8')

    println result.name // prints Luleå
}

我的问题的答案已经是 found on Stack Exchange

You just need to add the StringHttpMessageConverter to the template's message converters:

restTemplate.getMessageConverters()
    .add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));

根据 my previous answer:

您只需将 StringHttpMessageConverter 添加到模板的消息转换器中:

RestTemplate template = new RestTemplate();
template.getMessageConverters()
        .add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
ResponseEntity<Object> response = template.exchange(endpoint, method, entity, 
                                                    Object.class);

在我的例子中,我遇到了同样的问题,内容是从我的 REST Web 服务从服务器接收的,而不是我的本地环境。 我进行了很多搜索,最后找到了解决我问题的解决方案。 在 Windows 中,我添加了一个新的环境变量,键为:JAVA_TOOL_OPTIONS 并将其值设置为:-Dfile.encoding=UTF8。 每次启动 JVM 时都会自动设置 (Java) 系统 属性。您将知道该参数已被拾取,因为以下消息将发布到 System.err:

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8