Jackson
uses JacksonAnnotationIntrospector to handle standard annotations. We can extend this mechanism providing our extra introspector together with default. To do that we can use pair method.
Simple custom implementation could look like below:
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.introspect.Annotated;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import java.util.Objects;
public class SpringJacksonAnnotationIntrospector extends AnnotationIntrospector {
private final ApplicationContext context;
@Autowired
public SpringJacksonAnnotationIntrospector(ApplicationContext context) {
this.context = Objects.requireNonNull(context);
}
@Override
public JsonFormat.Value findFormat(Annotated memberOrClass) {
JsonFormat annotation = _findAnnotation(memberOrClass, JsonFormat.class);
if (annotation == null) {
return null;
}
String basePattern = annotation.pattern();
if (basePattern.startsWith("$")) {
String pattern = context.getEnvironment().getProperty(basePattern.substring(2, basePattern.length() - 1));
return JsonFormat.Value.forPattern(pattern);
}
return null;
}
@Override
public Version version() {
return new Version(1, 0, 0, "", "org.company", "spring-jackson");
}
}
Above implementation reuses JsonFormat
annotation but we can introduce new one to avoid confusion. We need to register our custom introspector. There is many different ways how to do that and it depends from your Spring
configuration. We can do that for example, like below:
import com.example.jackson.SpringJacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext context;
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//JSON
AnnotationIntrospector pairedIntrospectors = AnnotationIntrospector.pair(springJacksonAnnotationIntrospector(),
new JacksonAnnotationIntrospector());
converters.add(new MappingJackson2HttpMessageConverter(
Jackson2ObjectMapperBuilder.json()
.annotationIntrospector(pairedIntrospectors)
.build()));
}
@Bean
public SpringJacksonAnnotationIntrospector springJacksonAnnotationIntrospector() {
return new SpringJacksonAnnotationIntrospector(context);
}
}
Since now, Spring
's global configuration should be used to override date format.
See also: