Java – deserialization error handling
My question is simple: I have the following simple classes:
public class Foo { private int id = -1; public void setId(int _id){ this.id = _id; } public int getId(){ return this.id; } }
I'm trying to handle the following JSON:
{ "id": "blah" }
Obviously, there is a problem ("blah" cannot be resolved to int)
Before, Jackson threw something like org codehaus. jackson. map. Things like jsonmappingexception: you can't construct Java from string value 'blah' Instance of lang. integer: not a valid integer value
I agree with this, but I think somewhere it is allowed to ignore this type of mapping error I tried to register with a deserializationproblemhandler (see here), but it seems to apply only to unknown attributes rather than deserialization problems
Do you have any clues about this problem?
Solution
I successfully solved my problem. Thank you Tatu from Jackson ml
I had to use a custom non blocking deserializer for each primitive type processed in Jackson Factories like this:
public class JacksonNonBlockingObjectMapperFactory { /** * Deserializer that won't block if value parsing doesn't match with target type * @param <T> Handled type */ private static class NonBlockingDeserializer<T> extends JsonDeserializer<T> { private StdDeserializer<T> delegate; public NonBlockingDeserializer(StdDeserializer<T> _delegate){ this.delegate = _delegate; } @Override public T deserialize(JsonParser jp,DeserializationContext ctxt) throws IOException,JsonProcessingException { try { return delegate.deserialize(jp,ctxt); }catch (JsonMappingException e){ // If a JSON Mapping occurs,simply returning null instead of blocking things return null; } } } private List<StdDeserializer> jsonDeserializers = new ArrayList<StdDeserializer>(); public ObjectMapper createObjectMapper(){ ObjectMapper objectMapper = new ObjectMapper(); SimpleModule customJacksonModule = new SimpleModule("customJacksonModule",new Version(1,null)); for(StdDeserializer jsonDeserializer : jsonDeserializers){ // Wrapping given deserializers with NonBlockingDeserializer customJacksonModule.addDeserializer(jsonDeserializer.getValueClass(),new NonBlockingDeserializer(jsonDeserializer)); } objectMapper.registerModule(customJacksonModule); return objectMapper; } public JacksonNonBlockingObjectMapperFactory setJsonDeserializers(List<StdDeserializer> _jsonDeserializers){ this.jsonDeserializers = _jsonDeserializers; return this; } }
Then call it this way (pass only those you want to block as a deserializer):
JacksonNonBlockingObjectMapperFactory factory = new JacksonNonBlockingObjectMapperFactory(); factory.setJsonDeserializers(Arrays.asList(new StdDeserializer[]{ // StdDeserializer,here,comes from Jackson (org.codehaus.jackson.map.deser.StdDeserializer) new StdDeserializer.ShortDeserializer(Short.class,null),new StdDeserializer.IntegerDeserializer(Integer.class,new StdDeserializer.CharacterDeserializer(Character.class,new StdDeserializer.LongDeserializer(Long.class,new StdDeserializer.FloatDeserializer(Float.class,new StdDeserializer.DoubleDeserializer(Double.class,new StdDeserializer.NumberDeserializer(),new StdDeserializer.BigDecimalDeserializer(),new StdDeserializer.BigIntegerDeserializer(),new StdDeserializer.CalendarDeserializer() })); ObjectMapper om = factory.createObjectMapper();