Jackson: ignoring properties instead of throwing JsonMappingException

I have a class that needs to be deserialized from JSON using Jackson. The structure of the class is as follows:

public class A { public B b; } public class B { public List<C> c; } public class C { public String s; public Long l1; public Long l2; public Long l3; } 

Deserializing objects basically work fine; in addition, it interacts with a buggy code that emits an incorrect value when the list is empty. That is, instead of emitting:

 { "b" : { "c" : [] } } 

he emits:

 { "b" : { "c" : {} } } 

Jackson throws this exception when he encounters this:

 org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token at [Source: [ B@1ad5cabc ; line: 1, column: 896] (through reference chain: A["b"]->B["c"]) 

All of this makes sense, of course. The entry is incorrect.

However, an empty list in this case does not apply to any of the codes; if it were null , I would not care. Is there a way to tell Jackson to ignore this property (and keep null ) if it is not possible to deserialize?

I tried using my own deserializer:

 public class CListDeserializer extends JsonDeserializer<List<C>> { public CListDeserializer() { } @Override public List<C> deserialize(JsonParser arg0, DeserializationContext arg1) throws IOException, JsonProcessingException { try { return arg0.readValueAs(new TypeReference<List<C>>(){}); } catch (JsonMappingException jme) { } return null; } } 

And if I add annotation to the field:

 @JsonDeserialize(using=CListDeserializer.class) public List<C> c; 

Instead, I get this exception:

 org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type, class asgard.ChangeEntry] from JSON String; no single-String constructor/factory method (through reference chain: A["b"]) 

Please note that this exception only occurs if I try to deserialize the external type A - if I pulled out the internal serialized value for B and deserialize it, it works fine.

+4
source share
1 answer

I understood why the custom deserializer does not work: the readValueAs method consumes { , which readValueAs exception, leaving } as the next token. This closes the internal object, and then the parser will consider that the value of the enumerated number that occurs next time should be analyzed as an internal type, and not as an enumeration type.

I will try to do it tomorrow, but I think this is the way in the deserialize method:

 ObjectMapper om = ...; JsonNode node = arg0.readValueAs(JsonNode.class); try { return om.readValue(node, new TypeReference<List<C>>(){}); } catch (JsonMappingException jme) { } return null; 
+2
source

Source: https://habr.com/ru/post/1390537/


All Articles