【问题标题】:jackson disable @JsonFormat annotation杰克逊禁用@JsonFormat注解
【发布时间】:2020-01-29 13:09:13
【问题描述】:

我正在使用 jackson 库,并且遇到了一种情况,我想在序列化/反序列化时使用 objectmapper 禁用 @JsonFormat 注释。

我的 Api 代码在第 3 方库中,因此我无法删除/添加任何注释,因此 objectMapper 是唯一的选择。

API 类:

public class ApiClass {

  @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
  private DateTime time;

}

我的代码:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(Feature.ALLOW_COMMENTS, true);
objectMapper.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.setSerializationInclusion(Include.NON_ABSENT);
objectMapper.registerModule(new JodaModule());
objectMapper.registerModule(new JavaTimeModule());

String str = " {\"time\": \"2012-05-01\"}";

ApiClass msg = objectMapper.readValue(str, ApiClass.class);

我希望此转换成功发生。

目前我得到:com.fasterxml.jackson.databind.JsonMappingException: Invalid format: "2012-05-01" is too short

请帮帮我。

提前致谢

【问题讨论】:

  • 能否详细说明您遇到的具体问题?谢谢!
  • @RobStreeting:更新了上述问题。
  • 我试图复制这个..你能告诉你 API 类中 DateTime 的导入语句是什么吗?
  • @NawnitSen : 导入 o​​rg.joda.time.DateTime;

标签: java jackson jackson-databind jackson2 jackson-dataformat-xml


【解决方案1】:

下面是专门禁用 JsonFormat 的代码:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(Feature.ALLOW_COMMENTS, true);
objectMapper.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.setSerializationInclusion(Include.NON_ABSENT);
objectMapper.registerModule(new JodaModule());
objectMapper.registerModule(new JavaTimeModule());

objectMapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
    @Override
    protected <A extends Annotation> A _findAnnotation(final Annotated annotated,
        final Class<A> annoClass) {
      if (!annotated.hasAnnotation(JsonFormat.class)) {    //since we need to disable JsonFormat annotation.
        return super._findAnnotation(annotated, annoClass);
      }
      return null;
    }
  });


String str = " {\"time\": \"2012-05-01\"}";

ApiClass msg = objectMapper.readValue(str, ApiClass.class);
System.out.println(objectMapper.writeValueAsString(msg ));

如果我们需要禁用多个注释(JsonFormat,JsonUnWrapped),那么:

替换:

if (!annotated.hasAnnotation(JsonFormat.class)) {

与:

if (!annotated.hasOneOf(new Class[] {JsonFormat.class, JsonUnwrapped.class})) {

谢谢大家。

【讨论】:

    【解决方案2】:

    在使用readValue方法之前尝试下面的代码

    mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"));
    

    【讨论】:

    • 不起作用,得到:com.fasterxml.jackson.databind.JsonMappingException: Invalid format: "2012-05-01" is too short
    【解决方案3】:

    尝试使用自定义反序列化器:

    public class MyTest {
        @Test
        public void myTest() throws IOException {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
            objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
            objectMapper.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, true);
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
            objectMapper.registerModule(new JavaTimeModule());
    
            String str = " {\"time\": \"2012-05-01\"}";
    
    
            SimpleModule module = new SimpleModule();
            module.addDeserializer(DateTime.class, new DateTimeDeserializer());
            objectMapper.registerModule(module);
    
    
            ApiClass msg = objectMapper.readValue(str, ApiClass.class);
            System.out.println(msg.getTime());
        }
    }
    
    class ApiClass {
    
        @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
        private DateTime time;
    
        public DateTime getTime() {
            return time;
        }
    
        public void setTime(DateTime time) {
            this.time = time;
        }
    }
    
    class DateTimeDeserializer extends StdDeserializer<DateTime> {
    
        public DateTimeDeserializer() {
            this(null);
        }
    
        public DateTimeDeserializer(Class<?> vc) {
            super(vc);
        }
    
        @Override
        public DateTime deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException {
            JsonNode node = jp.getCodec().readTree(jp);
            String time = node.asText();
            return new DateTime(time);
        }
    }
    

    【讨论】:

    • 引起:java.lang.IllegalArgumentException:格式无效:“2012-05-01”太短
    • 我自己在本地测试过这个,这个工作,你使用的是哪个jackson和java版本
    • 您采用的模式不正确,@JsonFormat(pattern = "yyyy-MM-dd"),请检查我的问题中的模式。
    • 答案已更新,从 IDE 复制到此处是一个愚蠢的错误
    • 你甚至可以取消:objectMapper.registerModule(new JodaModule()) 因为无论如何你都必须编写自定义反序列化器
    【解决方案4】:

    这个问题有一个解决方案。

    请查看:https://www.baeldung.com/jackson-annotations 点号。 9 禁用杰克逊注解

    objectMapper.disable(MapperFeature.USE_ANNOTATIONS);
    ApiClass msg = objectMapper.readValue(str, ApiClass.class);
    
    sout(msg.getTime()) //2012-05-01T00:00:00.000Z
    

    但这会禁用所有注释。我只想禁用 @JsonFormat 注释。请提出建议。

    【讨论】:

    • 这是另一种方法,在您的特定用例中可能会很好。但是,如果有多个注释并且您只想取消其中一个注释,则可能会出现一个巨大的问题。
    • @VivekGupta:这是另一个问题了。你知道如何只禁用特定的注释吗?
    • 我不确定..我相信如果您遇到这个问题,那么您最好为 joda datetime 编写一个自定义反序列化器,并将其添加为我在下面的答案中给出的简单模块,而不是禁用注释,我分享的那个已经过测试
    • 是的,请查看我上面的答案。
    【解决方案5】:

    您可以使用 SimpleDateFormat 将字符串类型日期转换为日期类型,如下所示

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        try {
            Date parse = simpleDateFormat.parse(String date);
            return parse;
        } catch (ParseException e) {
            e.printStackTrace();
        }
    

    【讨论】:

      猜你喜欢
      • 2016-08-09
      • 2014-07-31
      • 2017-02-15
      • 1970-01-01
      • 2014-08-22
      • 2019-11-25
      • 1970-01-01
      • 2014-06-17
      • 1970-01-01
      相关资源
      最近更新 更多