【问题标题】:Deserialize MongoDB date fields to Java POJO Using Jackson使用 Jackson 将 MongoDB 日期字段反序列化为 Java POJO
【发布时间】:2017-03-17 11:55:39
【问题描述】:

使用 Spring Boot 1.4.4.RELEASE,已将 RequestBody 保存到 MongoDB,如下所示:

{
    "startTime" : NumberLong("1483542955570"),
    "startDate" : ISODate("2017-01-04T15:15:55.570Z"),
    "endTime" : NumberLong("1483542955570"),
    "endDate" : ISODate("2017-01-04T15:15:55.570Z")
}

在将其映射回 Java POJO 时,我正在尝试以下代码。

public <T> T getPOJOFromMongoDocument(Document resourceDocument, Class<T> clazz) {
        String serialize = JSON.serialize(resourceDocument);
        return objectMapper.readValue(serialize,
                                      clazz);
}

serialize 返回的日期字段如下

"startDate" : { "$date" : "2017-01-04T15:15:55.570Z"}

由于$date,JacksonObjectMapper在解析时返回如下异常:

java.lang.RuntimeException: Error parsing mongoDoc to Pojo : errorMessage : {Can not deserialize instance of java.util.Date out of START_OBJECT token at [Source: {
"startTime": 1483542955570,
"startDate": {
    "$date": "2017-01-04T15:15:55.570Z"
},
"endTime": 1483542955570,
"endDate": {
    "$date": "2017-01-04T15:15:55.570Z"
}}; line: 1, column: 381] (through reference chain: com.gofynd.engine.mongo.models.RuleWithDataVO["validity"]->com.gofynd.engine.mongo.models.ValidityVO["startDate"])}

有没有办法在不使用 ODM 的情况下解决这个问题?

【问题讨论】:

    标签: java json spring mongodb jackson


    【解决方案1】:

    当反序列化为 Date 时,Jackson 期望 String"2017-01-04T15:15:55.570Z"。相反,它在 JSON 中看到另一个对象({ 字符)的开始,因此出现异常。

    考虑指定您的Pojo 类和另一个类似于此的MongoDate 类:

    class MongoDate {
        @JsonProperty("$date")
        Date date;
    }
    
    class Pojo {
        long startTime;
        long endTime;
        MongoDate startDate;
        MongoDate endDate;
    }
    

    或者,如果您不能/不想添加 MongoDate 类,您可以为 Date 字段引入自定义反序列化器。在那种情况下Pojo

    class Pojo {
        long startTime;
        long endTime;
        @JsonDeserialize(using = MongoDateConverter.class)
        Date startDate;
        @JsonDeserialize(using = MongoDateConverter.class)
        Date endDate;
    }
    

    反序列化器看起来像这样:

    class MongoDateConverter extends JsonDeserializer<Date> {
        private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    
        @Override
        public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
            JsonNode node = jp.readValueAsTree();
            try {
                return formatter.parse(node.get("$date").asText());
            } catch (ParseException e) {
                return null;
            }
        }
    }
    

    【讨论】:

    • 但这需要更改 Java 数据结构。定制 Jackson (de)serializer 不是更好的解决方案吗?
    【解决方案2】:

    我回去尝试了使用反序列化器的类似方法。

    代码如下:

    public class MongoDateDeserializer extends JsonDeserializer<Date> {
    
    @Override
    public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode node = oc.readTree(jsonParser);
        String dateValue = node.get("$date")
                               .asText();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        Date date = null;
        try {
            date = df.parse(dateValue);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }}
    

    VO的变化如下:

    @JsonDeserialize(using = MongoDateDeserializer.class)
    private Date startDate;
    
    @JsonDeserialize(using = MongoDateDeserializer.class)
    private Date endDate;
    

    这已经成功了。 但是,如果 MongoDB 的 JSON.serialize 完成返回规范化 json 的工作会更好。希望在未来。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-08
      • 2020-12-10
      • 2018-05-31
      • 2014-10-22
      • 2012-04-07
      • 1970-01-01
      • 2013-01-08
      • 1970-01-01
      相关资源
      最近更新 更多