#java #json #spring #jackson
#java #json #spring #джексон
Вопрос:
У меня есть следующий класс, который я использую в качестве полезной нагрузки запроса :
public class SampleRequest {
private String fromDate;
private String toDate;
// Getters and setters removed for brevity.
}
Я пытаюсь использовать его с этим ресурсом ниже (просто пытаюсь вывести его на экран, чтобы увидеть, что происходит) :
@PostMapping("/getBySignatureOne")
public ResponseEntity<?> getRequestInfo(@Valid @RequestBody SampleRequest signatureOneRequest) {
System.out.println(signatureOneRequest.getToDate);
System.out.println(signatureOneRequest.getFromDate);
}
Это запрос JSON, который я отправляю :
{
"fromDate":"2019-03-09",
"toDate":"2019-03-10"
}
Это ошибка, которую я получаю :
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.test.app.payload.SampleRequest` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('fromDate'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.test.app.payload.SampleRequest` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('fromDate')
at [Source: (PushbackInputStream); line: 1, column: 2]]
Я хотел бы знать, что здесь не так, я подозреваю, что это проблема с конструкторами, или что я где-то пропускаю какую-то аннотацию, но я, честно говоря, не уверен, где я ошибся.
Комментарии:
1. Каков ваш запрос JSON? У вас есть конструкторы в SampleRequest? Если да, вам также необходимо иметь конструктор по умолчанию.
2. @cosmos — Бах, я знал, что забуду что-то предоставить!! Я только что отредактировал вопрос с помощью json, который я отправляю 🙂
3. Добавление конструктора по умолчанию сделало это за меня!
Ответ №1:
Вам нужен конструктор со всеми параметрами:
public SampleRequest(String fromDate, String toDate) {
this.fromDate = fromDate;
this.toDate = toDate;
}
Или с использованием @AllArgsConstructor
or @Data
из lombok.
Комментарии:
1. Ах, так что это исправило мою основную ошибку — но по какой-то причине я, кажется, вижу нулевые значения для полей, когда я печатаю их на экран… Есть идеи, что может быть причиной этого? Я также случайно открываю новый вопрос по этому поводу, если мы не хотим сорвать этот!
2. @slippy смотрите мой пост
Ответ №2:
В моем случае мне не хватало конструктора без аргументов
@Data
@AllArgsConstructor
@NoArgsConstructor
для тех, кто не использует Lombok, не добавляйте конструктор args в pojo сопоставления
public ClassA() {
super();
// TODO Auto-generated constructor stub
}
также не забудьте добавить компонент Restemplate в основной файл, если вы используете тот же
Ответ №3:
Привет, вам нужно написать пользовательский десериализатор, поскольку он не способен анализировать строку (от даты и до сегодняшнего дня) на сегодняшний день
{ «FromDate»: «2019-03-09», «ToDate»: «2019-03-10»}
по этой ссылке есть руководство по началу работы с пользовательским десериализатором https://www.baeldung.com/jackson-deserialization
Десериализатор может быть написан следующим образом.
public class CustomDateDeserializer extends StdDeserializer<Date> {
private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
public CustomDateDeserializer() {
this(null);
}
public CustomDateDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Date deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException {
String date = jsonparser.getText();
try {
return formatter.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}}
Вы можете зарегистрировать десериализатор в самом классе следующим образом.
@JsonDeserialize(using = ItemDeserializer.class)
public class Item { ...}
Или вы можете зарегистрировать пользовательский десериализатор вручную следующим образом
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Item.class, new ItemDeserializer());
mapper.registerModule(module);