【问题标题】:Cannot serialize LocalDate in Mongodb无法在 Mongodb 中序列化 LocalDate
【发布时间】:2015-03-04 04:42:43
【问题描述】:

我正在使用 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 无法序列化类型:class java.time.LocalDate 在 com.mongodb.util.ClassMapBasedObjectSerializer.serialize(ClassMapBasedObjectSerializer.java:77) 在 com.mongodb.util.JSONSerializers$MapSerializer.serialize(JSONSerializers.java:317) 在 com.mongodb.util.ClassMapBasedObjectSerializer.serialize(ClassMapBasedObjectSerializer.java:79) 在 com.mongodb.util.JSONSerializers$IterableSerializer.serialize(JSONSerializers.java:290) 在 com.mongodb.util.ClassMapBasedObjectSerializer.serialize(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) 在 web.MeasureAccess.firstTime(MeasureAccess.scala:52) 在 web.MeasureAccess$.main(MeasureAccess.scala:262) 在 web.MeasureAccess.main(MeasureAccess.scala) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:483) 在 com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

我正在使用 mongo-java-driver-2.13.0-rc1.jar 斯卡拉 2.11.4 和 java 1.8.0_25

为了完整性。

【问题讨论】:

    标签: java json mongodb scala


    【解决方案1】:

    As Oliver Gierke mentions here

    尚不支持此数据类型。我希望这将很快可用。

    【讨论】:

      【解决方案2】:

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

      所以你必须先将你的 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);
      

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

      【讨论】:

      • 感谢您对 Morphia 和 Jongo 的参考。我一定会查的。
      • 我应该评论说,在这一点上,对于 3.x 驱动程序,我发现对 Morphia 和 Jongo 的需求不太相关,因为使用 Jackson / Jackson4Bson 为少数人插入自定义序列化器要简单得多您可能需要的额外类型
      【解决方案3】:

      对于遇到此问题的任何人,以下转换器将使某人朝着正确的方向开始。这个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()));
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-10-24
        • 2019-07-07
        • 2020-09-25
        • 1970-01-01
        • 1970-01-01
        • 2019-10-16
        • 2021-06-09
        • 2018-09-29
        • 1970-01-01
        相关资源
        最近更新 更多