Не удается создать экземпляр `имени класса` (хотя, по крайней мере, на Creator существует)

#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);