Всем привет! Есть Restful вебсервис написанный с Spring Boot, который отдает entity с полем LocalDate
с контроллера. И есть клиент для него на Андроиде, но проблема в том, что при попытке получить ответ вылетает ошибка, что не может десериализовать LocalDate
. Попробовала решение - написать кастомный Deserializer и прописать соответствующую аннотацию над полем класса, но не сработало. Можно ли вообще эту проблему решить не со стороны сервера, а со стороны клиента?
Код десериализатора:
public class LocalDateDeserializerImpl extends StdDeserializer<LocalDate> {
public LocalDateDeserializerImpl() {
super(LocalDate.class);
}
@Override
public LocalDate deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return LocalDate.parse(parser.readValueAs(String.class));
}
}
Код контроллера:
@RestController
@AllArgsConstructor
class EmployeeRequestController {
@GetMapping(value = "/employee-requests/username/{username}")
List<EmployeeRequestResponse> getDaysWithDecision(
@PathVariable("username") String username,
@RequestParam(required = false)
@DateTimeFormat(iso = DATE) LocalDate date
) {
return employeeRequestService.getDatesWithEmployeeRequestStatuses(username, date);
}
}
Сама сущность:
@Builder
@Value
public class EmployeeRequestResponse {
String username;
@JsonDeserialize(using = LocalDateDeserializerImpl.class)
LocalDate date;
RequestStatus requestStatus;
}
Код в клиенте:
private class DaysTask extends AsyncTask<Void, Void, EmployeeRequestResponse[]> {
@Override
protected EmployeeRequestResponse[] doInBackground(Void... voids) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setAccept(Arrays.asList(new MediaType[]{MediaType.APPLICATION_JSON}));
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<EmployeeRequestResponse[]>httpEntity = new HttpEntity<>(httpHeaders);
RestTemplate template = new RestTemplate();
template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
EmployeeRequestResponse[] data2 = template.getForObject(Constants.URL.GET_DATES_FOR_EMPLOYEE, EmployeeRequestResponse[].class);
return data2;
}
Вот что с сервера приходит
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: appname, PID: 12352
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:353)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Cannot construct instance of `appname.EmployeeRequestResponse` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('2018-04-17')
at [Source: (com.android.okhttp.okio.RealBufferedSource$1); line: 1, column: 2] (through reference chain: java.lang.Object[][0]); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `appname.EmployeeRequestResponse` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('2018-04-17')
at [Source: (com.android.okhttp.okio.RealBufferedSource$1); line: 1, column: 2] (through reference chain: java.lang.Object[][0])
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readInternal(MappingJackson2HttpMessageConverter.java:126)
at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:147)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:76)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:484)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237)
at appname.MainActivity$DaysTask.doInBackground(MainActivity.java:136)
at appname.MainActivity$DaysTask.doInBackground(MainActivity.java:127)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `appname.EmployeeRequestResponse` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('2018-04-17')
at [Source: (com.android.okhttp.okio.RealBufferedSource$1); line: 1, column: 2] (through reference chain: java.lang.Object[][0])
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1031)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1366)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3072)
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readInternal(MappingJackson2HttpMessageConverter.java:123)
Такое в общем нашла решение, может корявое но работает. Просто напрямую считываю строки с Json-а и конвертирую как мне надо
private class DaysTask extends AsyncTask<Void, Void, LocalDate>{
@Override
protected LocalDate doInBackground(Void... voids) {
LocalDate date = null;
try {
URL url = new URL(Constants.URL.GET_DATES_FOR_EMPLOYEE);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream responseBody = connection.getInputStream();
InputStreamReader responseBodyReader =
new InputStreamReader(responseBody, "UTF-8");
JsonReader jsonReader = new JsonReader(responseBodyReader);
jsonReader.setLenient(true);
while (jsonReader.peek().equals(JsonToken.STRING)) {
String line = jsonReader.nextString();
date = LocalDate.parse(line, DateTimeFormatter.ISO_LOCAL_DATE);
break;
}
jsonReader.close();
connection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
return date;
}
Всем спасибо кто откликнулся и пытался помочь) Доброго всем дня!=)))
Пытаюсь подключится к удаленной базе данных на сервереВыдает ошибку:
Вопрос: как можно в jocl предать массив в виде аргумента?
Нужно заменить поменять местами глиф символа А и БЧто бы когда вводился символ А выводился символ Б и наоборот