0

컨트롤러에 POST 방법에 대한 Spring Rest Controller와 "command"/ DTO 개체가 있습니다. 필자는 "due"필드 중 하나 인 Calendar 객체 인 serializer/deserializer도 작성했습니다.Spring에서 Json Deserializer를 감지하지 못했습니다.

Jackson2 종속성은 pom.xml에 정의되어 있으므로 Spring에서 내 deserializer를 감지하고이를 사용하여 String 입력을 java.util.Calendar로 변환 할 것을 기대합니다. 그러나 "일치하는 편집자 또는 전환 전략을 찾을 수 없습니다."라는 예외가 발생합니다. 내 시리얼 라이저가 작동 중 ... 디시리얼라이저 만 작동하지 않습니다!

나머지 컨트롤러 (TaskController.java)

@Controller 
public class TasksController { 

    ... 

    @RequestMapping(value = "/tasks", method = RequestMethod.POST) 
    public @ResponseBody Task createTask(@Valid TasksCommand tasksCommand){ 

     Task task = new Task(); 
     task.setName(tasksCommand.getName()); 
     task.setDue(tasksCommand.getDue()); 
     task.setCategory(tasksCommand.getCategory()); 

     return task; 
    } 
} 

명령/DTO 객체 : 달력

public class TasksCommand { 

    @NotBlank 
    @NotNull 
    private String name; 

    @JsonDeserialize(using = CalendarDeserializer.class) 
    @JsonSerialize(using = CalendarSerializer.class) 
    private Calendar due; 

    private String category; 

    ... getters & setters ... 
} 

시리얼 - 내 사용자 지정 날짜 형식 달력

public class CalendarSerializer extends JsonSerializer<Calendar>{ 

     @Override 
     public void serialize(Calendar calendar, JsonGenerator jgen, SerializerProvider provider) 
       throws IOException, JsonProcessingException { 
      SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss Z"); // Z - RFC 822 time zone 

      jgen.writeString(simpleDateFormat.format(calendar.getTime())); 

     } 

} 

디시리얼라이저에 대한

public class CalendarDeserializer extends JsonDeserializer<Calendar> { 

    private static Logger logger = Logger.getLogger(CalendarDeserializer.class); 

    @Override 
    public Calendar deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) 
      throws IOException, JsonProcessingException { 

     String dateStr = jsonParser.getText(); 
     logger.info("deserializing date:" + dateStr); 

     return Calendar.getInstance(); 

    } 
} 

Maven에 Jackson2 종속성이 지정되어 있습니다. GET (코드는 여기에 표시되지 않음)을 수행하면 serializer가 올바르게 호출되고 "Task"객체의 JSON 출력이 표시됩니다. 내가

curl -X POST -d name=task1 -d category=weekly -d due=01/01/2013 http://localhost:8080/tasks 

아래로는 HTTP POST를 할 때

, 디시리얼라이저가 감지되지 않습니다 내가 시리얼 라이저가 감지하기 때문에 예외

Failed to convert property value of type java.lang.String to required type java.util.Calendar for property due; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Calendar] for property due: no matching editors or conversion strategy found 

를 얻을, 이해가 안 돼요 왜 deserializer가 감지되지 않고 올바르게 호출되는지. 내가 읽은 것부터 classpath에 Jackson2 라이브러리를 가지고 있다면 스프링에 의해 감지 될 것이고 자동으로 MappingJackson2HttpMessageConverter를 메시지 변환기 목록에 추가 할 것이다. 따라서이 코드는 HTTP POST의 문자열을 감지하여 디시리얼라이저를 사용하여 java.util.Calendar로 변환해야합니다. 내가 뭘 놓치고 있니?

답변

0

이것을 알아 냈습니다.

설명에 표시된 것처럼 Curl을 사용하여 HTTP POST를 만들 때 (-d 플래그 사용) POST는 "application/x-www-form-urlencoded"콘텐츠 유형으로 제공됩니다 (뒷부분에서 분명합니다. 웹 양식 데이터로). 이것은 Spring FormHttpMessageConverter 메시지 변환기를 트리거하고 MappingJackson2HttpMessageConverter 변환기는 실행되지 않습니다.

그러나 serializer와 디시리얼라이저는 Jackson 주석으로 주석 처리되며 MappingJackson2HttpMessageConverter만이이를 처리하는 방법을 알고 있습니다. 이 문제로 설명 된 예외가 발생합니다.

이 솔루션은 curl 명령에 JSON 데이터를 전달하는 것입니다 또한

curl -X POST -H "Content-Type: application/json" -d '{"name":"test1","due":"1/1/2013","category":"weekly"}' http://localhost:8080/tasks 

의 JSON 입력이 HTTP의 POST 호출의 본문에 제공하기 때문에, 우리는에서 @RequestBody 주석을 사용할 필요가 컨트롤러 메서드 서명.

@RequestMapping(value = "/tasks", method = RequestMethod.POST) 
    public @ResponseBody Task createTask(@RequestBody @Valid TasksCommand tasksCommand){ 

     Task task = new Task(); 
     task.setName(tasksCommand.getName()); 
     task.setDue(tasksCommand.getDue()); 
     task.setCategory(tasksCommand.getCategory()); 

     return task; 
    } 

이제 디시리얼라이저가 시작되고 입력 기한이 String에서 Calendar 객체로 올바르게 변환됩니다.

관련 문제