我有一个Spring Rest Controller和一个“命令”/ DTO对象,用于控制器上的POST方法。我还为其中一个字段“due”编写了一个序列化器/反序列化器 - 这是一个Calendar对象。
由于在pom.xml中定义了Jackson2依赖项,我希望Spring能够检测到我的反序列化器并使用它将String输入转换为java.util.Calendar。但是,我得到了“找不到匹配的编辑器或转换策略”的例外情况。我的序列化器正在工作......只有解串器不起作用!
Rest Controller(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(代码未在此处显示)时,正确调用了序列化程序,并且我看到了“Task”对象的JSON输出。
但是,当我按以下方式进行HTTP POST时
curl -X POST -d name=task1 -d category=weekly -d due=01/01/2013 http://localhost:8080/tasks
从未检测到反序列化器,我得到了异常
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
由于检测到序列化程序,我不明白为什么没有检测到并正确调用解串器。根据我的阅读,Spring将检测到类路径上的Jackson2库,它会自动将MappingJackson2HttpMessageConverter添加到消息转换器列表中。因此,此代码应检测HTTP POST中的字符串,并使用反序列化器将其转换为java.util.Calendar。我错过了什么?
答案 0 :(得分:0)
想出这个。
当使用Curl进行HTTP POST时,如描述中所示(带有-d标志),POST带有内容类型&#34; application / x-www-form-urlencoded&#34; (后见之明显而易见,因为它被视为网络表单数据)。这会触发Spring FormHttpMessageConverter消息转换器,而MappingJackson2HttpMessageConverter转换器永远不会被触发。
然而,序列化器和反序列化器使用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调用的主体,我们需要在Controller方法签名中使用@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对象。
答案 1 :(得分:0)
尝试自定义类
public class DateDeserializer implements JsonDeserializer<Date> {
@Override
public Date deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2) throws JsonParseException {
String date = element.getAsString();
return TimeService.parseDate(date,"yyyy-MM-dd'T'HH:mm:ss");
}
}
然后将其添加到您的gson构建器
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new DateDeserializer());
gsonBuilder.create().fromJson(eventsJson, yourTargetClass.class)