RestAssured - Unrecognized field, not marked as ignorable

2k views Asked by At

(Note: I've seen multiple questions answered on the topic of "Jackson complains about unrecognized properties", I've not found one using RestAssured's object mapper specifically)

I have a RestAssured test, and it works

@Test
public void objectMappingRelyingOnClassAnnotation() {

    User user = RestAssured.get("https://api.github.com/users/andrejss88")
            .as(User.class); // must have 'jackson-databind' dependency

    Assert.assertEquals(user.login, "andrejss88");
}

It works because the class is annotated, as explained e.g. here:

@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
    public String login;
    public int id;
}

However, I wanted to use the alternative way using the overloaded as() method and pass in my own mapper WITHOUT using the annotation:

<T> T as(Class<T> cls, ObjectMapper mapper);

But Jackson's mapper doesn't work:

@Test
public void objectMappingUsingSpecifiedMapper() {

    //  Doesn't compile - Jackson's ObjectMapper != RestAssured's Mapper
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    AnotherUser user = RestAssured.get("https://api.github.com/users/andrejss88")
            .as(AnotherUser.class, objectMapper);

    Assert.assertEquals(user.login, "andrejss88");
}

How can I define and pass my own mapper?

1

There are 1 answers

0
Andrejs On

It's necessary to implement RestAssured's Mapper interface, which, under the hood, can still use Jackson's mapper like so:

@Test
public void objectMappingUsingSpecifiedMapper() {

    AnotherUser user = RestAssured.get("https://api.github.com/users/andrejss88")
            .as(AnotherUser.class, getMapper());

    Assert.assertEquals(user.login, "andrejss88");
    Assert.assertEquals(user.id, 11834443);
}

// pre-Java8 way
private Jackson2Mapper getMapper() {
    return new Jackson2Mapper(new Jackson2ObjectMapperFactory() {
        @Override
        public ObjectMapper create(Type type, String s) {
            ObjectMapper om = new ObjectMapper().findAndRegisterModules();
            om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            return om;
        }
    });
}

// Java8+ way 
private Jackson2Mapper getMapperLambda() {
    return new Jackson2Mapper((type, s) -> {
        ObjectMapper om = new ObjectMapper().findAndRegisterModules();
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return om;
    });
}

Furthermore, you can define this mapper in RestAssured's global config like so:

(credit goes to Jason: https://groups.google.com/g/rest-assured/c/xi78ZMqlovU?pli=1)

RestAssured.config = RestAssuredConfig.config().objectMapperConfig(new ObjectMapperConfig().jackson2ObjectMapperFactory(
        new Jackson2ObjectMapperFactory() {
          @Override
          public ObjectMapper create(Type cls, String charset) {
            ObjectMapper om = new ObjectMapper().findAndRegisterModules();
            om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            return om;
          }          
          
        }
    ));