Jackson JsonDeserialize 没有被@QueryParam 调用
Jackson JsonDeserialize not being called for @QueryParam
我已经映射了一个自定义反序列化器以将 dd/MM/yyyy 模式上的字符串转换为 LocalDate,这样我就可以使用更具可读性的签名来调用我的服务..
这是我的 dto class,用作 Jersey @BeanParam 在层之间传输数据:
public class ProdutoFilterDto implements FilterDto {
private static final long serialVersionUID = -4998167328470565406L;
@QueryParam("dataInicial")
@JsonDeserialize(using = CustomLocalDateDeserializer.class)
private LocalDate dataInicial;
@QueryParam("dataInicial")
@JsonDeserialize(using = CustomLocalDateDeserializer.class)
private LocalDate dataFinal;
public LocalDate getDataInicial() {
return dataInicial;
}
public void setDataInicial(LocalDate dataInicial) {
this.dataInicial = dataInicial;
}
public LocalDate getDataFinal() {
return dataFinal;
}
public void setDataFinal(LocalDate dataFinal) {
this.dataFinal = dataFinal;
}
}
这是我的自定义解串器:
public class CustomLocalDateDeserializer extends JsonDeserializer<LocalDate> {
@Override
public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
final String data = p.getValueAsString();
return (LocalDate) formatter.parse(data);
}
}
它正在用于此球衣服务:
@Path("produto")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ProdutoService {
...
@GET
@Path("query")
@Override
public Response query(
@QueryParam("offset") @DefaultValue(value = "0") Integer offSet,
@QueryParam("limit") @DefaultValue(value = "10") Integer limit,
@BeanParam ProdutoFilterDto filter) { ... }
...
}
我是这样打电话的:
${host goes here}/produto/query?dataInicial=11/09/1992
问题是永远不会调用反序列化器方法并且 bean 参数变量保持为空。
MessageBodyReader
不用于 @QueryParam
。您似乎期望 Jackson MessageBodyReader
能够处理这种反序列化,但它并不是那样工作的。
相反,您需要使用 ParamConverter
, which will need to be registered through a ParamConverterProvider
。例如:
@Provider
public class LocalDateParamConverterProvider implements ParamConverterProvider {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
@Override
public <T> ParamConverter<T> getConverter(
Class<T> rawType, Type genericType, Annotation[] antns) {
if (LocalDate.class == rawType) {
return new ParamConverter<T>() {
@Override
public T fromString(String string) {
try {
LocalDate localDate = LocalDate.parse(string, formatter);
return rawType.cast(localDate);
} catch (Exception ex) {
throw new BadRequestException(ex);
}
}
@Override
public String toString(T t) {
LocalDate localDate = (LocalDate) t;
return formatter.format(localDate);
}
};
}
return null;
}
}
现在 LocalDate
将与 @QueryParam
和其他 @XxxParam
一起使用。
一些注意事项:
如果您的目标是将您的 @XxxParam
和 JSON 正文都解析为一个 bean,这将不起作用。我不确定这将如何工作,但我确定它会涉及很多黑客攻击,我不推荐它。
您对 (LocalDate)
的强制转换无效。这是对 java.time.format.Parsed
的非法转换。请参阅代码示例中的正确方法。
和上面一点有关。我花了一个小时的时间试图弄清楚为什么我会得到一个 404,使用你的解析代码。对于 404,我最后想到的地方是 ParamConverter
。但似乎 ParamConverter
中抛出的任何未捕获的异常都会导致 404。没有多大意义吧?头晕目眩导致我this, which led me to this,这似乎是一个糟糕的规范
"if the field or property is annotated with
@MatrixParam, @QueryParam or @PathParam then an implementation MUST generate an instance of
NotFoundException (404 status) that wraps the thrown exception and no entity
"
故事的寓意:确保在 ParamConverter
!
中捕获 任何 可能的异常
另请参阅:
我已经映射了一个自定义反序列化器以将 dd/MM/yyyy 模式上的字符串转换为 LocalDate,这样我就可以使用更具可读性的签名来调用我的服务..
这是我的 dto class,用作 Jersey @BeanParam 在层之间传输数据:
public class ProdutoFilterDto implements FilterDto {
private static final long serialVersionUID = -4998167328470565406L;
@QueryParam("dataInicial")
@JsonDeserialize(using = CustomLocalDateDeserializer.class)
private LocalDate dataInicial;
@QueryParam("dataInicial")
@JsonDeserialize(using = CustomLocalDateDeserializer.class)
private LocalDate dataFinal;
public LocalDate getDataInicial() {
return dataInicial;
}
public void setDataInicial(LocalDate dataInicial) {
this.dataInicial = dataInicial;
}
public LocalDate getDataFinal() {
return dataFinal;
}
public void setDataFinal(LocalDate dataFinal) {
this.dataFinal = dataFinal;
}
}
这是我的自定义解串器:
public class CustomLocalDateDeserializer extends JsonDeserializer<LocalDate> {
@Override
public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
final String data = p.getValueAsString();
return (LocalDate) formatter.parse(data);
}
}
它正在用于此球衣服务:
@Path("produto")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ProdutoService {
...
@GET
@Path("query")
@Override
public Response query(
@QueryParam("offset") @DefaultValue(value = "0") Integer offSet,
@QueryParam("limit") @DefaultValue(value = "10") Integer limit,
@BeanParam ProdutoFilterDto filter) { ... }
...
}
我是这样打电话的:
${host goes here}/produto/query?dataInicial=11/09/1992
问题是永远不会调用反序列化器方法并且 bean 参数变量保持为空。
MessageBodyReader
不用于 @QueryParam
。您似乎期望 Jackson MessageBodyReader
能够处理这种反序列化,但它并不是那样工作的。
相反,您需要使用 ParamConverter
, which will need to be registered through a ParamConverterProvider
。例如:
@Provider
public class LocalDateParamConverterProvider implements ParamConverterProvider {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
@Override
public <T> ParamConverter<T> getConverter(
Class<T> rawType, Type genericType, Annotation[] antns) {
if (LocalDate.class == rawType) {
return new ParamConverter<T>() {
@Override
public T fromString(String string) {
try {
LocalDate localDate = LocalDate.parse(string, formatter);
return rawType.cast(localDate);
} catch (Exception ex) {
throw new BadRequestException(ex);
}
}
@Override
public String toString(T t) {
LocalDate localDate = (LocalDate) t;
return formatter.format(localDate);
}
};
}
return null;
}
}
现在 LocalDate
将与 @QueryParam
和其他 @XxxParam
一起使用。
一些注意事项:
如果您的目标是将您的
@XxxParam
和 JSON 正文都解析为一个 bean,这将不起作用。我不确定这将如何工作,但我确定它会涉及很多黑客攻击,我不推荐它。您对
(LocalDate)
的强制转换无效。这是对java.time.format.Parsed
的非法转换。请参阅代码示例中的正确方法。和上面一点有关。我花了一个小时的时间试图弄清楚为什么我会得到一个 404,使用你的解析代码。对于 404,我最后想到的地方是
ParamConverter
。但似乎ParamConverter
中抛出的任何未捕获的异常都会导致 404。没有多大意义吧?头晕目眩导致我this, which led me to this,这似乎是一个糟糕的规范"if the field or property is annotated with @MatrixParam, @QueryParam or @PathParam then an implementation MUST generate an instance of NotFoundException (404 status) that wraps the thrown exception and no entity "
故事的寓意:确保在
ParamConverter
! 中捕获 任何 可能的异常
另请参阅: