I'm having an issue with a custom JsonDeserializer. I'm trying to use different implementations of an abstract class depending on the JSON message received by a Rest service call (if the data is an Array
use one and if it's a String
use another):
@Path("/rest/cipher")
public interface CipherManager {
@POST
@Consumes("application/json")
@Produces("application/json")
@Path("/encrypt")
public Response cipher(AbstractCipherRequestBean jsonRequestData);
}
The deserializer looks like this:
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);
}
}
The inheritance is the following:
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;
...
}
I believe that since both implementations are inheriting the @JsonDeserialize
annotation, each call to mapper.readValue(root, abstractCipherRequestBeanClass)
calles the deserialize
method again, ending in a StackOverflowError.
Is there a way to avoid this? Since at the end I'm calling the mapper
with an actual class, I thought it'd use the default mapper
implementation, not the CipherRequestDeserializer
one.
I finally found the solution. Just annotating my two subclasses like this was enough:
@JsonDeserialize(as = CipherRequestBean.class)
public class CipherRequestBean extends AbstractCipherRequestBean{
...
}
@JsonDeserialize(as = CipherMultRequestBean.class)
public class CipherMultRequestBean extends AbstractCipherRequestBean {
private List<String> b64Data;
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With