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
{ "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<>?!@#$%^&*()_+" }
Json string received in Java
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) }
What can i do to receive the string with latin special characters?
My code (end point):
@POST @Path("/testEncoding") @Consumes(MediaType.MULTIPART_FORM_DATA) public Response testEncoding(@Context HttpHeaders headers, MultipartFormDataInput multipart){ return interfaceOperationService.testEncoding(headers, multipart); }
Implementation:
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(); } }
and pom dependency:
<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-multipart-provider</artifactId> <version>4.5.8.Final</version> <scope>provided</scope> </dependency>
Advertisement
Answer
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
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<String, List<InputPart>>
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):
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); }