We have configured our spring boot app to not send null values back in json but we are still getting the null values back. The setup to not send null values using jackson ObjectMapper is in BootstrapConfig like this:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
..
...
@Bean
public ObjectMapper objectMapper() {
final SimpleDateFormat zuluDateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US);
zuluDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
final ObjectMapper jsonMapper = new ObjectMapper();
jsonMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
jsonMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
jsonMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
jsonMapper.registerModule(new JavaTimeModule());
jsonMapper.setDateFormat(zuluDateFormat);
jsonMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return jsonMapper;
}
We were earlier using:
implementation io.leangen.graphql:spqr:0.12.1
but after upgrade to 0.12.3 we are getting same results.
When we print the gradle dependencies we do have com.google.code.gson:gson as a dependency of another library.
Is it possible spqr is using gson rather than jackson for object mapping. That seems to be the case as when I convert my entity to json in my EntityMutation class I DO NOT see any null values. And if I convert that json back to an entity and return that entity then the front end does not get null values.
Is there any way to ensure that jackson object mapper is used and not gson or am I missing something else in my setup?
GraphQL SPQR isn't directly involved in serializing the result. This is squarely within Spring's turf. SPQR returns the result from a regular Spring controller method, and it's up to Spring to do what it wills. For what it's worth, I quickly tested with your exact example, and I got
nulls filtered out. So I think your problem is unrelated to SPQR. One thing that might happen is that something in your is callingApplicationConversionService.configure(FormatterRegistry). If this is called more than once, and Spring's autoconfiguration calls it once already, it will register 2ObjectMappers, and it's unpredictable which one gets used by Spring. You can inspectFormatterRegistryto see if it looks normal.That said, while GraphQL SPQR isn't involved in serialization, it is involved in deserialization, and it indeed does not automatically use the framework-wide
ObjectMapperinstance, but instead has its own. This is mostly because deserialization needs can vary greatly depending on the context (what it is acceptable in one context may not be acceptable in another) and detecting conflicting expectations can be awful to debug.But, if you're sure your client won't be negatively affected by the changes, all you need to do to tell SPQR to inherit the configuration is:
With this, all settings on the framework-wide
ObjectMapperwill also apply to your GraphQL API. But, be extremely careful when doing this:ObjectMapperin SPQR is used to detect deserializable fields for GraphQL input types, read input values etc, so a change that seems innocuous in one context can have unforeseen consequences elsewhere (this is why SPQR has its own instance by default). But, again, SPQR isn't involved in serialization, so you do not need to to customize the bean mentioned above.