【问题标题】:How to deserialize Jackson Json NULL String to Date with JsonFormat如何使用 JsonFormat 将 Jackson Json NULL 字符串反序列化为日期
【发布时间】:2015-03-23 07:37:12
【问题描述】:

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

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

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

但是,如果 JSON 字符串值为空,我会收到以下异常。 你能告诉我如何解决这个问题吗?我尝试了一些选项,但它们都是用于序列化的。

ObjectMapper objectMapper = new ObjectMapper();   
objectMapper.setSerializationInclusion(Include.NON_NULL); 
objectMapper.setSerializationInclusion(Include.NON_EMPTY);

例外:

java.lang.IllegalArgumentException:无法解析日期值“NULL”(格式:“dd-MMM-yyyy”):无法解析日期:“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)

谢谢 - 阿图尔

【问题讨论】:

    标签: json string date null jackson


    【解决方案1】:

    您的问题不在于 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;
    }
    

    以下测试表明有效日期、空值和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);
    }
    

    但是,如果您传递值 "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();
    }
    

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

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

    改为这样设置你的 pojo:

    public class DatePojo {
        @JsonProperty("date")
        @JsonDeserialize(converter = MyDateConverter.class)
        private Date date;
    }
    

    并提供一个转换器:

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

    那么,你应该准备好了。以下测试通过:

    @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
    }
    

    IMO,最好的方法是使用替代方法 1,您只需更改 JSON。

    【讨论】:

    • 非常感谢 wassgren !你真的发现了问题,实际上 Json 来自 Elasticsearch,它非常大,所以我没有注意到“NULL”日期:-)
    • @apald,如果这有助于解决您的问题,如果您“接受”答案(绿色勾号)以便将问题标记为已正确解决,那就太好了!
    猜你喜欢
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-20
    • 1970-01-01
    相关资源
    最近更新 更多