Usando Spring Boot 1.4.4.RELEASE, guardó un RequestBody en MongoDB como se muestra a continuación:
{ "startTime" : NumberLong("1483542955570"), "startDate" : ISODate("2017-01-04T15:15:55.570Z"), "endTime" : NumberLong("1483542955570"), "endDate" : ISODate("2017-01-04T15:15:55.570Z") }Mientras mapeo esto de nuevo a un Java POJO, estoy probando el siguiente código.
public <T> T getPOJOFromMongoDocument(Document resourceDocument, Class<T> clazz) { String serialize = JSON.serialize(resourceDocument); return objectMapper.readValue(serialize, clazz); }serializar tiene los campos de fecha devueltos de la siguiente manera
"startDate" : { "$date" : "2017-01-04T15:15:55.570Z"} Debido a $date , Jackson ObjectMapper devuelve la siguiente excepción durante el análisis:
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"])}¿Hay alguna forma de resolver esto sin usar un ODM?
Al deserializar a Date , Jackson espera una String como "2017-01-04T15:15:55.570Z" . En cambio, ve el comienzo de otro objeto (el { char) dentro del JSON, por lo tanto, la excepción.
Considere especificar su clase Pojo y otra clase MongoDate similar a esta:
class MongoDate { @JsonProperty("$date") Date date; } class Pojo { long startTime; long endTime; MongoDate startDate; MongoDate endDate; } Alternativamente, si no puede/no quiere agregar una clase MongoDate , puede introducir un deserializador personalizado para los campos de Date . En ese caso Pojo :
class Pojo { long startTime; long endTime; @JsonDeserialize(using = MongoDateConverter.class) Date startDate; @JsonDeserialize(using = MongoDateConverter.class) Date endDate; }Y el deserializador se vería así:
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; } } }Volví y probé un enfoque similar de usar un deserializador.
Aquí está el código:
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; }}Los cambios en VO son los siguientes:
@JsonDeserialize(using = MongoDateDeserializer.class) private Date startDate; @JsonDeserialize(using = MongoDateDeserializer.class) private Date endDate;Esto ha funcionado con éxito. Sin embargo, sería mejor si JSON.serialize de MongoDB hace el trabajo de devolver un json normalizado. Con suerte en el futuro.