Jackson hidden behavior.


I hate to find bugs in my automated tests code. It is a test. It is supposed to find bugs, not to hide them, right?
I use jackson for serialization/deserialization in my tests code. I use it since I started writing in Java. All projects I’ve been involved to were using jackson. I thought that I know what is it and how to use it. OK, lets go straight to the point.

Recently I saw field type mismatch in a test log, but test was positive. Jackson hasn’t thrown any exception. After some digging into jackson docs I found that jackson has type coercion which is enabled by default.

My test is could be described like this: make POST http request and verify response body. Json could be simplified to this:

{
  "id": 666444888,
  "name": "John Doe"
}

but the problem is that I expected id to be a String. I thought, that jackson will throw an exception with following DTO:

public class Person {
    public String id;
    public String name;
}

This DTO will work with both String id and Integer id. System under test is a service with public API. It can’t change contract types, clients application could break, because not everyone use jackson or other libraries don’t have such kind a type coercions.

I thought that Java strict type system and jackson will protect me from this kind of errors. But it haven’t 🙂 So, how to fix it? Luckily for me, this behavior can be changed. With following ObjectMapper configuration jackson will throw an InvalidFormatException:

var mapper = JsonMapper.builder()
    .withCoercionConfig(LogicalType.Textual,cfg -> cfg.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail))
    .build()
// next line will throw an exception if id field in json is an Integer
Person person = mapper.readValue(jsonBody, Person.class)

Be careful with libraries, folks. There could be hidden features like this which you don’t want to use.