我的DELETE请求接受应删除的Item
列表。
我想验证请求正文是Item
对象的有效列表。
example given in the Javalin docs没有提及列表。
为了使代码得以编译,我必须这样做:
TypedValidator<List> requestValidator = ctx.validatedBodyAsClass(List.class);
List<Item> items = requestValidator.getOrThrow();
logger.info("Received delete request for {}", Arrays.toString(items.toArray()));
logger.info("items is type {}", items.getClass());
for (Item item : items) {
logger.info("Deleting {}", item.name);
}
验证通过,并且在下面的行中正确打印了
ctx
正文。问题是,在
getOrThrow()
处有未经检查的分配,并且实际上循环不起作用:[qtp1679441380-34] INFO com.myorg.MyClass - Received delete request for [{name=FooName, type=BarType}]
[qtp1679441380-34] INFO com.ericsson.cdzm.ws.controllers.ScheduleController - items is type class java.util.ArrayList
[qtp1679441380-34] WARN io.javalin.core.ExceptionMapper - Uncaught exception
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.myorg.Item
at com.myorg.MyClass.deleteItems(MyClass.java:51)
编辑:
java.util.LinkedHashMap
似乎是因为实际上items
是ArrayList<LinkedHashMap<String,String>>
类型。换句话说,Javalin根本没有解析或验证正文内容!它仅将Json name=value
映射转换为Java Map。验证传入的Json并将其解析为
Item
列表的更好方法是什么?我已经在Javalin 2.6.0和2.8.0上进行了测试。
最佳答案
我错过了,并且在Javalin文档中找不到的是我必须使用数组类型而不是参数化Collection类型。这有效:
TypedValidator<Item[]> requestValidator = ctx.bodyValidator(Item[].class);
List<Item> items = Arrays.asList(requestValidator.get());
还是,我想知道为什么会这样-我怀疑它与Java的类型系统有关吗?
我还可以直接访问Jackson ObjectMapper对象并使用它like you would use Jackson。缺点是我无法从Javalin的
BadRequestResponse
等自动抛出中受益。我认为使用数组类型为此付出的代价很小。 try {
List<ScheduleRequest> items = JavalinJackson.getObjectMapper().readValue(ctx.body(), new TypeReference<List<ScheduleRequest>>(){});
} catch (IOException e) {
throw new BadRequestResponse(e.getMessage());
}