0

My server return results having 2 different types: SearchResultDTO when successefull and String when error. I need to handle these 2 types and return always SearchResultDTO type. Here is my deserializer:

public class SearchResultsDeserializer extends JsonDeserializer<SearchResultDTO> {

    @Override
    public SearchResultDTO deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        JsonToken t = jp.getCurrentToken();
        if (t == JsonToken.VALUE_STRING){
            return new SearchResultDTO(jp.getText());
        } else {
            return jp.readValueAs(SearchResultDTO.class);
        }
    }
}

When i run this code and server send SearchResultDTO object, jackson go in infinite loop by calling this function and returns with error: "java.lang.StackOverflowError: stack size 1036KB"

Johnny Depp
  • 35
  • 1
  • 7

1 Answers1

0

Easy fix would be to create new instance of ObjectMapper in your SearchResultsDeserializer and use it instead of JsonParser

public static class SearchResultsDeserializer extends JsonDeserializer<SearchResultDTO> {
    private static ObjectMapper mapper = new ObjectMapper();
    @Override
    public SearchResultDTO deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        JsonToken t = jp.getCurrentToken();
        if (t == JsonToken.VALUE_STRING){
            return new SearchResultDTO(jp.getText());
        } else {
            return mapper.readValue(jp, SearchResultDTO.class);
        }
    }
}

The hard way is to save default deserializer in your custom deserializer. Here is more info: How do I call the default deserializer from a custom deserializer in Jackson

Community
  • 1
  • 1
varren
  • 14,551
  • 2
  • 41
  • 72
  • @JohnnyDepp if you are 100% sure that you have competly different mapper without `SearchResultsDeserializer` registered on him, you probably have to show us the rest of your code. Because this 100% works for me, here is demo https://gist.github.com/varren/38b76c4a62fc5024caedcdc469606649 I think you registered your deserializer with annotation and this way i think there is nothng that can help you. If you use annotations, you will have to write custom implementation for `jp.readValueAs(SearchResultDTO.class);` – varren May 19 '16 at 09:30
  • 1
    @JohnnyDepp but why do you need a deserializer at the first place. You just give error sting in your constructor with string arg. And jackson can understand that. The default behavior would be to use String args constructor if you give string instead of object in your json. – varren May 19 '16 at 09:36
  • good point about default constructor. Probably i will choose this way. But i wanted to make some universal solution for future usage. And yes, i register deserializer with annotations. – Johnny Depp May 20 '16 at 20:22