使用继承的自定义 JsonDeserializer 导致 StackOverflowError
Custom JsonDeserializer using inheritance causes StackOverflowError
我在使用自定义 JsonDeserializer 时遇到问题。我正在尝试使用抽象 class 的不同实现,具体取决于 Rest 服务调用收到的 JSON 消息(如果数据是 Array
使用一个,如果它是 String
使用另一个):
@Path("/rest/cipher")
public interface CipherManager {
@POST
@Consumes("application/json")
@Produces("application/json")
@Path("/encrypt")
public Response cipher(AbstractCipherRequestBean jsonRequestData);
}
反序列化器如下所示:
public class CipherRequestDeserializer extends JsonDeserializer<AbstractCipherRequestBean> {
@Override
public AbstractCipherRequestBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
ObjectNode root = (ObjectNode) mapper.readTree(jp);
Class<? extends AbstractCipherRequestBean> abstractCipherRequestBeanClass = null;
Iterator<Entry<String, JsonNode>> elementsIterator = root.getFields();
while (elementsIterator.hasNext()) {
Entry<String, JsonNode> element = elementsIterator.next();
String name = element.getKey();
if(name.equals("b64Data")){
if(element.getValue().isArray()){
abstractCipherRequestBeanClass = CipherMultRequestBean.class;
}else{
abstractCipherRequestBeanClass = CipherRequestBean.class;
}
}
}
if (abstractCipherRequestBeanClass == null){
return null;
}
return mapper.readValue(root, abstractCipherRequestBeanClass);
}
}
继承如下:
public class RequestBean {
protected String b64Data;
...
}
@JsonDeserialize(using = CipherRequestDeserializer.class)
public abstract class AbstractCipherRequestBean extends RequestBean{
...
}
public class CipherRequestBean extends AbstractCipherRequestBean{
...
}
public class CipherMultRequestBean extends AbstractCipherRequestBean {
private List<String> b64Data;
...
}
我相信,由于两个实现都继承了 @JsonDeserialize
注释,因此每次调用 mapper.readValue(root, abstractCipherRequestBeanClass)
都会再次调用 deserialize
方法,并以 WhosebugError 结束。
有没有办法避免这种情况?由于最后我用实际的 class 调用 mapper
,我认为它会使用默认的 mapper
实现,而不是 CipherRequestDeserializer
实现。
我终于找到了解决办法。像这样注释我的两个子类就足够了:
@JsonDeserialize(as = CipherRequestBean.class)
public class CipherRequestBean extends AbstractCipherRequestBean{
...
}
@JsonDeserialize(as = CipherMultRequestBean.class)
public class CipherMultRequestBean extends AbstractCipherRequestBean {
private List<String> b64Data;
...
}
我在使用自定义 JsonDeserializer 时遇到问题。我正在尝试使用抽象 class 的不同实现,具体取决于 Rest 服务调用收到的 JSON 消息(如果数据是 Array
使用一个,如果它是 String
使用另一个):
@Path("/rest/cipher")
public interface CipherManager {
@POST
@Consumes("application/json")
@Produces("application/json")
@Path("/encrypt")
public Response cipher(AbstractCipherRequestBean jsonRequestData);
}
反序列化器如下所示:
public class CipherRequestDeserializer extends JsonDeserializer<AbstractCipherRequestBean> {
@Override
public AbstractCipherRequestBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
ObjectNode root = (ObjectNode) mapper.readTree(jp);
Class<? extends AbstractCipherRequestBean> abstractCipherRequestBeanClass = null;
Iterator<Entry<String, JsonNode>> elementsIterator = root.getFields();
while (elementsIterator.hasNext()) {
Entry<String, JsonNode> element = elementsIterator.next();
String name = element.getKey();
if(name.equals("b64Data")){
if(element.getValue().isArray()){
abstractCipherRequestBeanClass = CipherMultRequestBean.class;
}else{
abstractCipherRequestBeanClass = CipherRequestBean.class;
}
}
}
if (abstractCipherRequestBeanClass == null){
return null;
}
return mapper.readValue(root, abstractCipherRequestBeanClass);
}
}
继承如下:
public class RequestBean {
protected String b64Data;
...
}
@JsonDeserialize(using = CipherRequestDeserializer.class)
public abstract class AbstractCipherRequestBean extends RequestBean{
...
}
public class CipherRequestBean extends AbstractCipherRequestBean{
...
}
public class CipherMultRequestBean extends AbstractCipherRequestBean {
private List<String> b64Data;
...
}
我相信,由于两个实现都继承了 @JsonDeserialize
注释,因此每次调用 mapper.readValue(root, abstractCipherRequestBeanClass)
都会再次调用 deserialize
方法,并以 WhosebugError 结束。
有没有办法避免这种情况?由于最后我用实际的 class 调用 mapper
,我认为它会使用默认的 mapper
实现,而不是 CipherRequestDeserializer
实现。
我终于找到了解决办法。像这样注释我的两个子类就足够了:
@JsonDeserialize(as = CipherRequestBean.class)
public class CipherRequestBean extends AbstractCipherRequestBean{
...
}
@JsonDeserialize(as = CipherMultRequestBean.class)
public class CipherMultRequestBean extends AbstractCipherRequestBean {
private List<String> b64Data;
...
}