MinifyingHttpMessageConverter.java
/*
* Copyright 2026 Global Crop Diversity Trust
* Licensed under the Apache License, Version 2.0
* See LICENSE file in project root folder or http://www.apache.org/licenses/LICENSE-2.0
*/
package org.gringlobal.spring;
import java.io.IOException;
import org.gringlobal.custom.json.serializer.SortJsonSerializer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
import com.fasterxml.jackson.databind.module.SimpleModule;
/**
* Custom HttpMessageConverter produces a JSON that doesn't contain properties with a NULL values.
* Also, it excludes properties: "ownedBy", "ownedDate", "createdBy", "createdDate", "modifiedBy", "modifiedDate".
*/
public class MinifyingHttpMessageConverter extends MappingJackson2HttpMessageConverter {
public static final String APPLICATION_MINIFIED_JSON_VALUE = "application/minified-json";
public static final MediaType APPLICATION_MINIFIED_JSON = MediaType.valueOf(APPLICATION_MINIFIED_JSON_VALUE);
public MinifyingHttpMessageConverter(ObjectMapper objectMapper) {
final SimpleModule customModule = new SimpleModule().addSerializer(new SortJsonSerializer());
final ObjectMapper customObjectMapper = objectMapper.registerModule(customModule).copy();
customObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
@JsonIgnoreProperties({ "ownedBy", "ownedDate", "createdBy", "createdDate", "modifiedBy", "modifiedDate" })
abstract class MixIn {
}
customObjectMapper.setMixInResolver(new ClassIntrospector.MixInResolver() {
@Override
public Class<?> findMixInClassFor(Class<?> cls) {
return MixIn.class;
}
@Override
public ClassIntrospector.MixInResolver copy() {
return this;
}
});
super.setObjectMapper(customObjectMapper);
}
@Override
protected boolean canRead(MediaType mediaType) {
// Never use this converter to read JSON input
return false;
}
@Override
protected boolean canWrite(MediaType mediaType) {
return mediaType != null && (mediaType.isCompatibleWith(APPLICATION_MINIFIED_JSON));
}
@Override
protected void addDefaultHeaders(HttpHeaders headers, Object o, MediaType contentType) throws IOException {
// override produced content type to `application/json`
super.addDefaultHeaders(headers, o, MediaType.APPLICATION_JSON);
}
}