如何使用JsonFormat将Jackson Json NULL String反序列化为Date

apa*_*ald 3 string null json date jackson

我看了很多,但到目前为止仍然无法得到答案,任何帮助都非常感谢!

我有一个简单StringDate字段映射,并尝试将JSON字符串读取到Java对象.

@JsonInclude(value=Include.NON_EMPTY)
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd-MMM-yyyy", timezone="PST")
protected Date eolAnnounceDate;
Run Code Online (Sandbox Code Playgroud)

但是,如果JSON字符串值为空,则会出现以下异常.你能告诉我怎么解决这个问题吗?我尝试了一些选项,但它们都是为了序列化.

ObjectMapper objectMapper = new ObjectMapper();   
objectMapper.setSerializationInclusion(Include.NON_NULL); 
objectMapper.setSerializationInclusion(Include.NON_EMPTY);
Run Code Online (Sandbox Code Playgroud)

例外:

java.lang.IllegalArgumentException:无法解析Date值'NULL'(格式:"dd-MMM-yyyy"):Unparseable date:"NULL"com.fasterxml.jackson.databind.deser.std.DateDeserializers $ DateBasedDeserializer._parseDate( DateDeserializers.java:180)com.fasterxml.jackson.databind.deser.std.DateDeserializers $ DateDeserializer.deserialize(DateDeserializers.java:279)com.fasterxml.jackson.databind.deser.std.DateDeserializers $ DateDeserializer.deserialize(DateDeserializers. java:260)com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:464)com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98)com.fasterxml. jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:295)com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:230)com.fasterxml.jackson.databind.deser.std. CollectionDeserializer.deserialize(CollectionDeserializer.java:207)com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23)com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java: 464)com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98)com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:295)com.fasterxml.jackson. databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)com.cisco.cre.dao.impl.ElasticsearchDAOImpl.getListByIdsFilter(ElasticsearchDAOImpl.的java:94)

谢谢 - 阿图尔

was*_*ren 15

您的问题不是在JSON中传递空值.问题是JSON包含一个具有该值的字符串"NULL".

因此,为了解决这个问题,有许多可行的方法.我认为以下两个将适用于这种情况.

备选方案1:修复JSON

第一种方法是修复JSON,使其不包含字符串值"NULL",而是包含值null(未引用)或只是跳过它.

想象一下以下POJO:

public class DatePojo {
    @JsonInclude(value= JsonInclude.Include.NON_EMPTY)
    @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd-MMM-yyyy", timezone="PST")
    @JsonProperty("date")
    private Date date;
}
Run Code Online (Sandbox Code Playgroud)

以下测试显示有效日期,空值和null值有效:

@Test
public void testJson() throws IOException {
    String jsonWithValidDate = "{\"date\":\"12-Jun-1982\"}";
    String jsonWithNoDate = "{}";
    String jsonWithNullDate = "{\"date\":null}";

    ObjectMapper mapper = new ObjectMapper();
    final DatePojo pojoWithValidDate = mapper.readValue(jsonWithValidDate, DatePojo.class);
    final DatePojo pojoWithNoDate = mapper.readValue(jsonWithNoDate, DatePojo.class);
    final DatePojo pojoWithNullDate = mapper.readValue(jsonWithNullDate, DatePojo.class);

    Assert.assertNotNull(pojoWithValidDate.date);
    Assert.assertNull(pojoWithNoDate.date);
    Assert.assertNull(pojoWithNullDate.date);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果传递该值,"NULL"则测试失败,因为"NULL"无法将其解析为日期:

@Test(expected = JsonMappingException.class)
public void testInvalidJson() throws IOException {
    String jsonWithNullString = "{\"date\":\"NULL\"}";

    ObjectMapper mapper = new ObjectMapper();
    mapper.readValue(jsonWithNullString, DatePojo.class); // Throws the exception
    Assert.fail();
}
Run Code Online (Sandbox Code Playgroud)

备选方案2:提供自己的转换器来处理 "NULL"

如果无法修复JSON(如备选方案1中所述),您可以提供自己的转换器.

改为设置你的pojo:

public class DatePojo {
    @JsonProperty("date")
    @JsonDeserialize(converter = MyDateConverter.class)
    private Date date;
}
Run Code Online (Sandbox Code Playgroud)

并提供一个转换器:

public class MyDateConverter extends StdConverter<String, Date> {
    @Override
    public Date convert(final String value) {
        if (value == null || value.equals("NULL")) {
            return null;
        }
        try {
            return new SimpleDateFormat("dd-MMM-yyyy").parse(value);
        } catch (ParseException e) {
            throw new IllegalStateException("Unable to parse date", e);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,你应该全力以赴.以下测试通过:

@Test
public void testJson() throws IOException {
    String jsonWithValidDate = "{\"date\":\"12-Jun-1982\"}";
    String jsonWithNoDate = "{}";
    String jsonWithNullDate = "{\"date\":null}";
    String jsonWithNullString = "{\"date\":\"NULL\"}"; // "NULL"

    ObjectMapper mapper = new ObjectMapper();
    final DatePojo pojoWithValidDate = mapper.readValue(jsonWithValidDate, DatePojo.class);
    final DatePojo pojoWithNoDate = mapper.readValue(jsonWithNoDate, DatePojo.class);
    final DatePojo pojoWithNullDate = mapper.readValue(jsonWithNullDate, DatePojo.class);
    final DatePojo pojoWithNullStr = mapper.readValue(jsonWithNullString, DatePojo.class); // Works

    Assert.assertNotNull(pojoWithValidDate.date);
    Assert.assertNull(pojoWithNoDate.date);
    Assert.assertNull(pojoWithNullDate.date);
    Assert.assertNull(pojoWithNullStr.date); // Works
}
Run Code Online (Sandbox Code Playgroud)

IMO,最好的方法是使用备选方案1,只需更改JSON即可.

  • @apald,如果这有助于解决您的问题,那么如果您"接受"答案(绿色勾号)以便将问题标记为正确解决将会很好! (2认同)