Skip to content

Instantly share code, notes, and snippets.

@chenyhd
Created December 1, 2019 12:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chenyhd/907967f47912efe430e65bdc08185ca9 to your computer and use it in GitHub Desktop.
Save chenyhd/907967f47912efe430e65bdc08185ca9 to your computer and use it in GitHub Desktop.
Jackson return empty instead of null
package xx.xx;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
import com.fasterxml.jackson.databind.ser.SerializerFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class CustomNullSerializer extends DefaultSerializerProvider {
// A couple of constructors and factory methods to keep the compiler happy
public CustomNullSerializer() {
super();
}
public CustomNullSerializer(CustomNullSerializer provider, SerializationConfig config,
SerializerFactory jsf) {
super(provider, config, jsf);
}
@Override
public CustomNullSerializer createInstance(SerializationConfig config,
SerializerFactory jsf) {
return new CustomNullSerializer(this, config, jsf);
}
// This is the interesting part. When the property has a null value it will call this method to get the
// serializer for that null value. At this point, we have the BeanProperty, which contains information about
// the field that we are trying to serialize (including the type!) So we can discriminate on the type to determine
// which serializer is used to output the null value.
@Override
public JsonSerializer<Object> findNullValueSerializer(BeanProperty property) throws JsonMappingException {
if (property.getType().getRawClass().equals(String.class)) {
return EmptyStringSerializer.INSTANCE;
} else if (property.getType().getRawClass().equals(List.class)) { // You can also add ArrayList,LinkedList etc
return new JsonSerializer<Object>() {
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartArray();
gen.writeEndArray();
}
};
} else if (property.getType().getRawClass().equals(Map.class)) { // You can also add HashMap,TreeMap etc
return new JsonSerializer<Object>() {
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeEndObject();
}
};
} else {
return super.findNullValueSerializer(property);
}
}
// This is our fancy serializer that takes care of writing the value desired in the case of a null string. We could
// write whatever we want in here, but in order to maintain backward compatibility we choose the empty string
// instead of something like "joel is awesome."
public static class EmptyStringSerializer extends JsonSerializer<Object> {
public static final JsonSerializer<Object> INSTANCE = new EmptyStringSerializer();
private EmptyStringSerializer() {
}
// Since we know we only get to this seralizer in the case where the value is null and the type is String, we can
// do our handling without any additional logic and write that empty string we are so desperately wanting.
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException, JsonProcessingException {
jsonGenerator.writeString("");
}
}
}
package xx.xx;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import java.util.List;
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(customJackson2HttpMessageConverter());
super.configureMessageConverters(converters);
}
@Bean
public MappingJackson2HttpMessageConverter customJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializerProvider(new CustomNullSerializer());
jsonConverter.setObjectMapper(objectMapper);
return jsonConverter;
}
}
@chenyhd
Copy link
Author

chenyhd commented Dec 1, 2019

I quoted some other websites (such as StackOverflow, baeldung and so on) code and combined it to make it look more complete, but I can't find the website I referred to before. If you find the original code you can contact me and I will add the original author.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment