json 如何告诉 RestTemplate 使用 UTF-8 编码进行 POST?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29392422/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 17:49:13  来源:igfitidea点击:

How can I tell RestTemplate to POST with UTF-8 encoding?

jsonspringresttemplate

提问by anssias

I'm having problems posting JSON with UTF-8 encoding using RestTemplate. Default encoding for JSON is UTF-8 so the media type shouldn't even contain the charset. I have tried to put charset in the MediaType but it doesn't seem to work anyway.

我在使用 RestTemplate 发布带有 UTF-8 编码的 JSON 时遇到问题。JSON 的默认编码是 UTF-8,因此媒体类型甚至不应该包含字符集。我试图在 MediaType 中放入字符集,但它似乎不起作用。

My code:

我的代码:

String dataJson = "{\"food\": \"sm?rrebr?d\"}";
HttpHeaders headers = new HttpHeaders();
MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
headers.setContentType(mediaType);

HttpEntity<String> entity = new HttpEntity<String>(dataJson, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Boolean> formEntity = restTemplate.exchange(postUrl, HttpMethod.POST, entity, Boolean.class);

回答by mushfek0001

You need to add StringHttpMessageConverter to rest template's message converter with charset UTF-8. Like this

您需要添加 StringHttpMessageConverter 以使用字符集 UTF-8 休息模板的消息转换器。像这样

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
        .add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));

回答by Rohit

(Adding to solutions by mushfek0001 and zhouji)

(添加到 mushfek0001 和 zhouji 的解决方案中)

By default RestTemplate has ISO-8859-1StringHttpMessageConverter which is used to convert a JAVA object to request payload.

默认情况下,RestTemplate 具有ISO-8859-1StringHttpMessageConverter,用于将 JAVA 对象转换为请求负载。

Difference between UTF-8 and ISO-8859:

UTF-8 和 ISO-8859 的区别:

UTF-8 is a multibyte encoding that can represent any Unicode character. ISO 8859-1 is a single-byte encoding that can represent the first 256 Unicode characters. Both encode ASCII exactly the same way.

UTF-8 是一种多字节编码,可以表示任何 Unicode 字符。ISO 8859-1 是一种单字节编码,可以表示前 256 个 Unicode 字符。两者都以完全相同的方式对 ASCII 进行编码。

Solution 1 (copied from mushfek001):

解决方案1(从mushfek001复制):

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

Solution 2:

解决方案2:

Though above solution works, but as zhouji pointed out, it will add two string converters and it may lead to some regression issues.

虽然上述解决方案有效,但正如zhouji所指出的,它会添加两个字符串转换器,可能会导致一些回归问题。

If you set the right content type in http header, then ISO 8859 will take care of changing the UTF characters.

如果您在 http 标头中设置了正确的内容类型,则 ISO 8859 将负责更改 UTF 字符。

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

or

或者

// HttpUriRequest request
request.addHeader("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);

回答by zhouji

The answer by @mushfek0001 produce two StringHttpMessageConverterwhich will send two text/plainand */*, such as the debug picture.

@mushfek0001 的答案产生两个StringHttpMessageConverter,将发送两个text/plain*/*,例如调试图片。

enter image description here

在此处输入图片说明

Even the Acceptheader of client will be:

甚至Accept客户端的标题也将是:

text/plain, text/plain, */*, */*

So the better one is removethe ISO-8859-1 StringHttpMessageConverterand use single UTF-8 StringHttpMessageConverter.

所以更好的方法是删除ISO-8859-1StringHttpMessageConverter并使用单个 UTF-8 StringHttpMessageConverter

Use this:

用这个:

RestTemplate restTemplate = new RestTemplate();
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
stringHttpMessageConverter.setWriteAcceptCharset(true);
for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) {
    if (restTemplate.getMessageConverters().get(i) instanceof StringHttpMessageConverter) {
        restTemplate.getMessageConverters().remove(i);
        restTemplate.getMessageConverters().add(i, stringHttpMessageConverter);
        break;
    }
}

回答by Ran Adler

restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_16LE));

String response = restTemplate.getForObject(url, String.class);

回答by Sandesh

Adding new StringHttpMessageConverter won't help. In existing StringHttpMessageConverter we need to set writeAcceptCharset to false and build httpheader with charset we want.

添加新的 StringHttpMessageConverter 无济于事。在现有的 StringHttpMessageConverter 中,我们需要将 writeAcceptCharset 设置为 false 并使用我们想要的字符集构建 httpheader。

RestTemplate restTemplate = new RestTemplate();
   List<HttpMessageConverter<?>> c = restTemplate.getMessageConverters();
        for(HttpMessageConverter<?> mc :c){
            if (mc instanceof StringHttpMessageConverter) {
                StringHttpMessageConverter mcc = (StringHttpMessageConverter) mc;
                mcc.setWriteAcceptCharset(false);
            }
   }

  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
  headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
  HttpEntity<String> entity = new HttpEntity<String>(jsonPayload, headers);

  restTemplate.postForEntity(postResourceUrl, entity, String.class);

回答by pankaj desai

Better you should remove the StringHttpMessageConverter first before adding new. so this way you will have one instance of StringHttpMessageConverter in our MessageConverters list.

最好在添加新的之前先删除 StringHttpMessageConverter。因此,这样您将在我们的 MessageConverters 列表中拥有一个 StringHttpMessageConverter 实例。

RestTemplate restTemplate = new RestTemplate();
        final Iterator<HttpMessageConverter<?>> iterator = restTemplate.getMessageConverters().iterator();
        while (iterator.hasNext()) {
            final HttpMessageConverter<?> converter = iterator.next();
            if (converter instanceof StringHttpMessageConverter) {
                iterator.remove();
            }
        }


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

回答by Michel Jung

Removing the existing converter, but with Java 8 (why do people still write Java 7 Code anyways?)

删除现有的转换器,但使用 Java 8(为什么人们仍然编写 Java 7 代码?)

List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
converters .removeIf(httpMessageConverter -> httpMessageConverter instanceof StringHttpMessageConverter);
messageConverters
  .add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));

回答by aqiao

Try this

尝试这个

restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(Charsets.UTF_8));