Java JSON字符串问题编码多部分

huangapple go评论140阅读模式
英文:

Java JSON String problem encoding Multipart

问题

我正在开发一个接收 MultipartFormDataInput 对象 (org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput) 的 REST API,这个对象是来自一个 form-data 的 Vue.js 应用。在数据字段中包含一个包含拉丁重音字符(á, é, í, ó, ú, ñ)的 JSON 字符串。在 Java 中打印 JSON 数据时,我得到了以下结果:

原始的 JSON 字符串:

  1. {
  2. "code": "123456789",
  3. "form": "test",
  4. "pot": "special character ñ",
  5. "categoria": "acción",
  6. "propiedad": "algún",
  7. "diligencia": "ábaco",
  8. "actual": "grabé",
  9. "pais": "Abstraído",
  10. "vivio_otro_pais_cual": "word without special characters... OK 1 2 3<>?!@#$%^&*()_+"
  11. }

在 Java 中接收到的 JSON 字符串:

  1. 11:04:32,086 INFO [stdout] (default task-1) JSON VALUES.... {
  2. 11:04:32,087 INFO [stdout] (default task-1) "code": "123456789",
  3. 11:04:32,087 INFO [stdout] (default task-1) "form": "test",
  4. 11:04:32,087 INFO [stdout] (default task-1) "pot": "special character ??",
  5. 11:04:32,087 INFO [stdout] (default task-1) "categoria": "acci??n",
  6. 11:04:32,087 INFO [stdout] (default task-1) "propiedad": "alg??n",
  7. 11:04:32,087 INFO [stdout] (default task-1) "diligencia": "??baco",
  8. 11:04:32,087 INFO [stdout] (default task-1) "actual": "grab??",
  9. 11:04:32,087 INFO [stdout] (default task-1) "pais": "Abstra??do",
  10. 11:04:32,087 INFO [stdout] (default task-1) "vivio_otro_pais_cual": "word without special characters... OK 1 2 3<>?!@#$%^&*()_+"
  11. 11:04:32,087 INFO [stdout] (default task-1) }

要如何接收带有拉丁特殊字符的字符串?

我的代码(端点):

  1. @POST
  2. @Path("/testEncoding")
  3. @Consumes(MediaType.MULTIPART_FORM_DATA)
  4. public Response testEncoding(@Context HttpHeaders headers, MultipartFormDataInput multipart){
  5. return interfaceOperationService.testEncoding(headers, multipart);
  6. }

实现:

  1. public Response testEncoding(HttpHeaders headers, MultipartFormDataInput multipart) {
  2. try {
  3. String dataJson = multipart.getFormDataPart("data", String.class, null);
  4. String valorCodificado = new String (dataJson.getBytes(StandardCharsets.US_ASCII), StandardCharsets.UTF_8);
  5. System.out.println("JSON VALUES.... " + dataJson);
  6. System.out.println("JSON ENCODING.... " + valorCodificado);
  7. StringBuilder sb = new StringBuilder();
  8. for (String header : headers.getRequestHeaders().keySet()) {
  9. sb.append(header + ":" + headers.getRequestHeader(header) + "\n");
  10. }
  11. System.out.println(sb.toString());
  12. return Response.status(200).entity(valorCodificado).build();
  13. } catch (Exception e) {
  14. // TODO: handle exception
  15. return Response.status(500).entity("ERROR").build();
  16. }
  17. }

以及 pom 依赖:

  1. <dependency>
  2. <groupId>org.jboss.resteasy</groupId>
  3. <artifactId>resteasy-multipart-provider</artifactId>
  4. <version>4.5.8.Final</version>
  5. <scope>provided</scope>
  6. </dependency>
英文:

I’m developing a REST API that receives a MultipartFormDataInput object (org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput), this comes from a form-data Vue.js app. On the data field comes a json string that contains latin accent characters (á, é, í, ó, ú, ñ). When print the json data in Java I get this:

Original Json string

  1. {
  2. &quot;code&quot;: &quot;123456789&quot;,
  3. &quot;form&quot;: &quot;test&quot;,
  4. &quot;pot&quot;: &quot;special character &#241;&quot;,
  5. &quot;categoria&quot;: &quot;acci&#243;n&quot;,
  6. &quot;propiedad&quot;: &quot;alg&#250;n&quot;,
  7. &quot;diligencia&quot;: &quot;&#225;baco&quot;,
  8. &quot;actual&quot;: &quot;grab&#233;&quot;,
  9. &quot;pais&quot;: &quot;Abstra&#237;do&quot;,
  10. &quot;vivio_otro_pais_cual&quot;: &quot;word without special characters... OK 1 2 3&lt;&gt;?!@#$%^&amp;*()_+&quot;
  11. }

Json string received in Java

  1. 11:04:32,086 INFO [stdout] (default task-1) JSON VALUES.... {
  2. 11:04:32,087 INFO [stdout] (default task-1) &quot;code&quot;: &quot;123456789&quot;,
  3. 11:04:32,087 INFO [stdout] (default task-1) &quot;form&quot;: &quot;test&quot;,
  4. 11:04:32,087 INFO [stdout] (default task-1) &quot;pot&quot;: &quot;special character ??&quot;,
  5. 11:04:32,087 INFO [stdout] (default task-1) &quot;categoria&quot;: &quot;acci??n&quot;,
  6. 11:04:32,087 INFO [stdout] (default task-1) &quot;propiedad&quot;: &quot;alg??n&quot;,
  7. 11:04:32,087 INFO [stdout] (default task-1) &quot;diligencia&quot;: &quot;??baco&quot;,
  8. 11:04:32,087 INFO [stdout] (default task-1) &quot;actual&quot;: &quot;grab??&quot;,
  9. 11:04:32,087 INFO [stdout] (default task-1) &quot;pais&quot;: &quot;Abstra??do&quot;,
  10. 11:04:32,087 INFO [stdout] (default task-1) &quot;vivio_otro_pais_cual&quot;: &quot;word without special characters... OK 1 2 3&lt;&gt;?!@#$%^&amp;*()_+&quot;
  11. 11:04:32,087 INFO [stdout] (default task-1) }
  12. 11:04:32,088 INFO [stdout] (default task-1) JSON ENCODING.... {
  13. 11:04:32,088 INFO [stdout] (default task-1) &quot;code&quot;: &quot;123456789&quot;,
  14. 11:04:32,088 INFO [stdout] (default task-1) &quot;form&quot;: &quot;test&quot;,
  15. 11:04:32,088 INFO [stdout] (default task-1) &quot;pot&quot;: &quot;special character ??&quot;,
  16. 11:04:32,088 INFO [stdout] (default task-1) &quot;categoria&quot;: &quot;acci??n&quot;,
  17. 11:04:32,088 INFO [stdout] (default task-1) &quot;propiedad&quot;: &quot;alg??n&quot;,
  18. 11:04:32,088 INFO [stdout] (default task-1) &quot;diligencia&quot;: &quot;??baco&quot;,
  19. 11:04:32,088 INFO [stdout] (default task-1) &quot;actual&quot;: &quot;grab??&quot;,
  20. 11:04:32,088 INFO [stdout] (default task-1) &quot;pais&quot;: &quot;Abstra??do&quot;,
  21. 11:04:32,088 INFO [stdout] (default task-1) &quot;vivio_otro_pais_cual&quot;: &quot;word without special characters... OK 1 2 3&lt;&gt;?!@#$%^&amp;*()_+&quot;
  22. 11:04:32,088 INFO [stdout] (default task-1) }

What can i do to receive the string with latin special characters?

My code (end point):

  1. @POST
  2. @Path(&quot;/testEncoding&quot;)
  3. @Consumes(MediaType.MULTIPART_FORM_DATA)
  4. public Response testEncoding(@Context HttpHeaders headers, MultipartFormDataInput multipart){
  5. return interfaceOperationService.testEncoding(headers, multipart);
  6. }

Implementation:

  1. public Response testEncoding(HttpHeaders headers, MultipartFormDataInput multipart) {
  2. try {
  3. String dataJson = multipart.getFormDataPart(&quot;data&quot;, String.class, null);
  4. String valorCodificado = new String (dataJson.getBytes(StandardCharsets.US_ASCII), StandardCharsets.UTF_8);
  5. System.out.println(&quot;JSON VALUES.... &quot; + dataJson);
  6. System.out.println(&quot;JSON ENCODING.... &quot; + valorCodificado);
  7. StringBuilder sb = new StringBuilder();
  8. for (String header : headers.getRequestHeaders().keySet()) {
  9. sb.append(header + &quot;:&quot; + headers.getRequestHeader(header) + &quot;\n&quot;);
  10. }
  11. System.out.println(sb.toString());
  12. return Response.status(200).entity(valorCodificado).build();
  13. } catch (Exception e) {
  14. // TODO: handle exception
  15. return Response.status(500).entity(&quot;ERROR&quot;).build();
  16. }
  17. }

and pom dependency:

  1. &lt;dependency&gt;
  2. &lt;groupId&gt;org.jboss.resteasy&lt;/groupId&gt;
  3. &lt;artifactId&gt;resteasy-multipart-provider&lt;/artifactId&gt;
  4. &lt;version&gt;4.5.8.Final&lt;/version&gt;
  5. &lt;scope&gt;provided&lt;/scope&gt;
  6. &lt;/dependency&gt;

答案1

得分: 1

所以在多部分内容中,每个消息体部分都是一个独立的实体,具有自己独立的内容类型。如果您在客户端请求中没有为每个部分设置内容类型,则会假定为 text/plain。在 RESTEasy 实现的情况下,默认为 text/plain; charset=ISO-8859-1

>InputPart.DEFAULT_CONTENT_TYPE_PROPERTY<br>
>如果在多部分消息的某个部分中未发送内容类型头,则会假定为 "text/plain; charset=ISO-8859-1"。

许多客户端无法为每个部分设置内容类型头。因此,您应该为它们设置内容类型头。对于这个部分,您希望它是 application/json; chartset=utf-8。设置头的方法是从 MultiPartFormDataInput 获取 InputPart。不要使用 getFormDataPart() 方法,而要使用 getFormDataMap() 方法,以获得返回类型为 Map&lt;String, List&lt;InputPart&gt;&gt;。从那里获取 InputPart 并调用 InputPart#setMediaTye(),然后可以使用 InputPart#getBody() 变体之一获取数据。类似于(未经测试):

  1. Map&lt;String, List&lt;InputPart&gt;&gt; inputParts = multipart.getFormDataMap();
  2. List&lt;InputPart&gt; dataParts = inputParts.get(&quot;data&quot;);
  3. if (dataParts != null &amp;&amp; !dataParts.isEmpty()) {
  4. InputPart dataPart = dataParts.get(0);
  5. dataPart.setMediaType(MediaType.APPLICATION_JSON + &quot;; chartset=utf-8&quot;);
  6. String dataPartJson = dataPart.getBody(String.class, null);
  7. // 或者如果您创建了一个 POJO,则数据将由 Jackson 进行反序列化
  8. DataPojo dataPartPogo = dataPart.getBody(DataPojo.class, null);
  9. }
英文:

So in multipart, each body part is its own separate entity with its own separate content-type. If you don't set the content-type for each part in the client request, it is assumed to be text/plain. In the case of RESTEasy implementation, it is text/plain; charset=ISO-8859-1.

>InputPart.DEFAULT_CONTENT_TYPE_PROPERTY<br>
>If no content-type header is sent in a multipart message part "text/plain; charset=ISO-8859-1" is assumed.

A lot of clients are not able to set the content-type header for each part. So what you should do is set the content-type header for them. For this part, you want it to be application/json; chartset=utf-8. How you set the header is by getting the InputPart from the MultiPartFormDataInput. Instead of using the getFormDataPart() method, use the getFormDataMap() method to get a Map&lt;String, List&lt;InputPart&gt;&gt; return type. From there, get the InputPart and call InputPart#setMediaTye(), then you can get the data with one of the InputPart#getBody() variants. Something like (not tested):

  1. Map&lt;String, List&lt;InputPart&gt;&gt; inputParts = multipart.getFormDataMap();
  2. List&lt;InputPart&gt; dataParts = inputParts.get(&quot;data&quot;);
  3. if (dataParts != null &amp;&amp; !dataParts.isEmpty()) {
  4. InputPart dataPart = dataParts.get(0);
  5. dataPart.setMediaType(MediaType.APPLICATION_JSON + &quot;; chartset=utf-8&quot;);
  6. String dataPartJson = dataPart.getBody(String.class, null);
  7. // of if you make a POJO the data will get deserialized by Jackson
  8. DataPojo dataPartPogo = dataPart.getBody(DataPojo.class, null);
  9. }

huangapple
  • 本文由 发表于 2020年10月20日 00:25:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/64431456.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定