We are using Swagger generated code for a restful server and models, and the problem is that the json payload can be updated with new properties at any point which will result in an error.
Typically, one can add @JsonIgnoreProperties(ignoreUnknown = true) to ignore properties, but in this case the Swagger generated model is generated each build (and is read only).
How can we set Swagger model to ignore unknown properties?
Sample error:
Unrecognized field "abc" (class xyz.model.sample), not marked as ignorable ....
UPDATE based on Paul's response:
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.annotation.Priority;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
@Provider
@Priority(Integer.MIN_VALUE)
public class ObjectMapperResolver implements
ContextResolver<ObjectMapper>{
private ObjectMapper mapper;
public ObjectMapperResolver() {
mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
}
@Override
public ObjectMapper getContext(Class<?> cls) {
return mapper;
}
}
Use a ContextResolver to configure the ObjectMapper globally. There is a DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES that we can set to false, to tell Jackson not to worry about unknown properties.
@Provider
public class ObjectMapperResolver implements ContextResolver<ObjectMapper> {
private ObjectMapper mapper;
public ObjectMapperResolver() {
mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
@Override
public ObjectMapper getContext(Class<?> cls) {
return mapper;
}
}
The Jackson JAX-RS provider will call this resolver to get the ObjectMapper it uses for deserialization.
If you are using scanning to register your resources and providers, then this class should automatically be registered because of the @Provider annotation. If you are not using scanning, then you need to make sure that you register this resolver, or else it won't be used.
If the Swagger codegen is already creating a ContextResolver, what you can do is just instantiate it in your resolver, and get the ObjectMapper from that resolver instead of creating your own mapper. This ensures that any configurations to the ObjectMapper made in the generated resolver still take effect. Then add a @Priority(Integer.MIN_VALUE) to the class so it is guaranteed to be used over the generated one, should the generated one also be registered.
@Provider
@Priority(Integer.MIN_VALUE)
public class ObjectMapperResolver implements ContextResolver<ObjectMapper> {
private ObjectMapper mapper;
public ObjectMapperResolver() {
JSON swaggerResolver = new JSON();
mapper = swaggerResolver.getContext(null);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
@Override
public ObjectMapper getContext(Class<?> cls) {
return mapper;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With