无法在Mongodb中序列化LocalDate

我使用java 8 java.time.LocalDate来解析日期。

但是尝试将一个LocalDate对象插入到mongodb中。 我在java驱动程序中遇到错误:

private def writeData(measure: DBCollection, installation: Int, date: String, dates: ListBuffer[LocalDate], values: ListBuffer[BigDecimal], validated: Boolean, overwrite: Boolean) { val timeValues: BasicDBList = new BasicDBList var i = 0 while ( i < dates.size ) { val obj: BasicDBObject = new BasicDBObject("time", dates(i)) obj.put("value", values(i).toString()) timeValues.add(obj) i += 1 } if ( debug ) System.out.println("Storedata: " + timeValues.toString) <-- error here 

错误日志:

java.lang.RuntimeException:json无法序列化类型:com.mongodb.util.ClassMapBasedObjectSerializer.serialize(ClassMapBasedObjectSerializer.java:77)中的类java.time.LocalDate,位于com.mongodb.util.JSONSerializers $ MapSerializer.serialize(JSONSerializers) .java:317)com.mongodb.util.ClassMapBasedObjectSerializer.serialize(ClassMapBasedObjectSerializer.java:79)at com.mongodb.util.JSONSerializers $ IterableSerializer.serialize(JSONSerializers.java:290)at com.mongodb.util.ClassMapBasedObjectSerializer。序列化(ClassMapBasedObjectSerializer.java:79)com.mongodb.util.JSON.serialize(JSON.java:54)com.mongodb.util.JSON.serialize(JSON.java:40)com.mongodb.BasicDBList.toString (BasicDBList.java:38)web.MeasureAccess.writeData(MeasureAccess.scala:203)at web.MeasureAccess.firstTime(MeasureAccess.scala:52)at web.MeasureAccess $ .main(MeasureAccess.scala:262)at web。在sun.reflect.N的sun.reflect.NativeMethodAccessorImpl.invoke0(本地方法)处的MeasureAccess.main(MeasureAccess.scala) 位于com.intellij.rt.execution的java.lang.reflect.Method.invoke(Method.java:483)的sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)中的ativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) .application.AppMain.main(AppMain.java:134)

我使用的是mongo-java-driver-2.13.0-rc1.jar Scala 2.11.4和java 1.8.0_25

为了完整。

不幸的是,MongoDB驱动程序使用java.util.Date类型,请参阅此处的文档

因此,您必须首先将LocalDate转换为Date实例,例如:

 MongoClient mongoClient = new MongoClient("localhost", 27017); DB db = mongoClient.getDB("test"); DBCollection coll = db.getCollection("testcol"); LocalDate ld = LocalDate.now(); Instant instant = ld.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant(); Date date = Date.from(instant); BasicDBObject doc = new BasicDBObject("localdate", date); coll.insert(doc); 

我建议使用像Morphia或Jongo这样的东西来包装MongoDB驱动程序,因为您可以注册全局映射器以隐式执行这些转换,以便您可以在域模型中使用LocalDate等

对于遇到此问题的任何人,以下转换器会让某人开始朝着正确的方向前进。 此TypeConverterDateLocalDateTime之间进行转换(由于OP特别询问了LocalDate,因此进行了区分)。

将以下转换器添加到Morphia,如下所示:

 morphia.getMapper().getConverters().addConverter(new LocalDateTimeConverter()); 

这是转换器类:

 public class LocalDateTimeConverter extends TypeConverter implements SimpleValueConverter { public LocalDateTimeConverter() { // TODO: Add other date/time supported classes here // Other java.time classes: LocalDate.class, LocalTime.class // Arrays: LocalDateTime[].class, etc super(LocalDateTime.class); } @Override public Object decode(Class targetClass, Object fromDBObject, MappedField optionalExtraInfo) { if (fromDBObject == null) { return null; } if (fromDBObject instanceof Date) { return ((Date) fromDBObject).toInstant().atZone(ZoneOffset.systemDefault()).toLocalDateTime(); } if (fromDBObject instanceof LocalDateTime) { return fromDBObject; } // TODO: decode other types throw new IllegalArgumentException(String.format("Cannot decode object of class: %s", fromDBObject.getClass().getName())); } @Override public Object encode(Object value, MappedField optionalExtraInfo) { if (value == null) { return null; } if (value instanceof Date) { return value; } if (value instanceof LocalDateTime) { ZonedDateTime zoned = ((LocalDateTime) value).atZone(ZoneOffset.systemDefault()); return Date.from(zoned.toInstant()); } // TODO: encode other types throw new IllegalArgumentException(String.format("Cannot encode object of class: %s", value.getClass().getName())); } } 

正如Oliver Gierke在这里提到的那样

此数据类型尚不支持。 我希望很快就会有这个。