【问题标题】:Set external date format pattern to @JsonFormat from a properties file从属性文件将外部日期格式模式设置为 @JsonFormat
【发布时间】:2021-03-14 02:50:28
【问题描述】:

我们正在尝试使用 @JSONFormat 将 bean 中的日期格式外部化为字段,以使其可配置。

@JsonFormat(pattern = "${application.date.format}")
private Date creationtime;

@JsonFormat(pattern = "yyyy-MM-DD")
private Date creationtime;

当我给出一个标准的字符串值时它会起作用。但是,当我们将第一个值中所示的值外部化时,我收到一个异常消息:

java.lang.IllegalArgumentException: Illegal pattern character 'p'

要将变量值分配给第二种方法,我们需要一个作为常量表达式的最终字符串。如何使模式可配置?

【问题讨论】:

  • 这不起作用,因为 Spring 不知道 @JsonFormat 所以它不会替换该值。这仅适用于 @Value 或明确支持此的基于 Spring 的注释。
  • @M. Deinum 有没有其他方法可以实现这一目标?注释属性值需要一个常量表达式,所以我也不能使用带有 @Value 的属性。
  • 不带注释。您将需要全局配置 jackson 或使用自定义序列化程序来动态执行此操作。

标签: java spring jackson


【解决方案1】:

Jackson 使用JacksonAnnotationIntrospector 处理标准注释。我们可以扩展这个机制,提供我们额外的自省器和默认值。为此,我们可以使用pair 方法。

简单的自定义实现如下所示:

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");
    }
}

上面的实现重用了JsonFormat注解,但我们可以引入新的注解以避免混淆。我们需要注册我们的自定义内省器。有许多不同的方法可以做到这一点,这取决于您的 Spring 配置。例如,我们可以这样做,如下所示:

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);
    }
}

从现在开始,Spring 的全局配置应该用于覆盖日期格式。

另见:

【讨论】:

    猜你喜欢
    • 2014-07-31
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 2016-01-10
    • 1970-01-01
    • 2019-03-13
    • 2019-04-29
    • 2016-10-17
    相关资源
    最近更新 更多