【问题标题】:Java JSON String problem encoding MultipartJava JSON String 编码 Multipart 问题
【发布时间】:2021-02-02 11:20:33
【问题描述】:

我正在开发一个 REST API,它接收一个 MultipartFormDataInput 对象 (org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput),它来自一个表单数据 Vue.js 应用程序。数据字段上有一个包含拉丁重音字符(á、é、í、ó、ú、ñ)的 json 字符串。在 Java 中打印 json 数据时,我得到这个:

原始Json字符串

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

Java 接收到的 JSON 字符串

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

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

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

我的代码(终点):

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

实施:

public Response testEncoding(HttpHeaders headers, MultipartFormDataInput multipart) {

    try {
                
        String dataJson = multipart.getFormDataPart("data", String.class, null);
        String valorCodificado = new String (dataJson.getBytes(StandardCharsets.US_ASCII), StandardCharsets.UTF_8);
        System.out.println("JSON VALUES.... " + dataJson);
        System.out.println("JSON ENCODING.... " + valorCodificado);
                
        StringBuilder sb = new StringBuilder();
        for (String header : headers.getRequestHeaders().keySet()) {
            sb.append(header + ":" + headers.getRequestHeader(header) + "\n");
        }        
        
        System.out.println(sb.toString());
                
        return Response.status(200).entity(valorCodificado).build();
    
    } catch (Exception e) {
        // TODO: handle exception
        return Response.status(500).entity("ERROR").build();
    }
}

和pom依赖:

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-multipart-provider</artifactId>
    <version>4.5.8.Final</version>
    <scope>provided</scope>
</dependency>

【问题讨论】:

    标签: java json jax-rs multipartform-data


    【解决方案1】:

    因此,在多部分中,每个正文部分都是其自己的独立实体,具有自己独立的内容类型。如果您没有为客户端请求中的每个部分设置 content-type,则假定为text/plain。在RESTEasy实现的情况下,是text/plain; charset=ISO-8859-1

    InputPart.DEFAULT_CONTENT_TYPE_PROPERTY
    如果在多部分消息中未发送内容类型标头,则假定为“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() 变体之一获取数据。类似的东西(未测试):

    Map<String, List<InputPart>> inputParts = multipart.getFormDataMap();
    List<InputPart> dataParts = inputParts.get("data");
    if (dataParts != null && !dataParts.isEmpty()) {
        InputPart dataPart = dataParts.get(0);
        dataPart.setMediaType(MediaType.APPLICATION_JSON + "; chartset=utf-8");
        String dataPartJson = dataPart.getBody(String.class, null);
        // of if you make a POJO the data will get deserialized by Jackson
        DataPojo dataPartPogo = dataPart.getBody(DataPojo.class, null);
    }
    

    【讨论】:

    • 你是对的,媒体类型是MediaType.APPLICATION_JSON_TYPE,工作正常
    猜你喜欢
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 1970-01-01
    • 2010-10-07
    相关资源
    最近更新 更多