如何在电梯JSON中序列化和反序列化Java 8 dateTime?

时间:2015-07-17 06:25:46

标签: java json scala datetime lift-json

我有一个我想先序列化的案例类。然后,我想将它反序列化以便在MongoDB中存储,但是java 8 LocalDateTime正在产生问题。我从这个链接中获得了帮助: how to deserialize DateTime in Lift 但没有运气。我无法为java 8日期时间写它。 任何人都可以帮我解决这个日期时间问题吗?这是我的代码:

import net.liftweb.json.Serialization.{read, write}

implicit val formats = Serialization.formats(NoTypeHints) 

case class Child(var str: String, var Num: Int, var abc: Option[String], MyList: List[Int], val dateTime: LocalDateTime = LocalDateTime.now())
val ser = write(Child("Mary", 5, None, List(1, 2)))
println("Child class converted to string" + ser) 

var obj = read[Child](ser)
println("object of Child is " + obj)

以下是控制台上打印的错误消息:

(run-main-0) java.lang.ArrayIndexOutOfBoundsException: 49938
java.lang.ArrayIndexOutOfBoundsException: 49938
    at com.thoughtworks.paranamer.BytecodeReadingParanamer$ClassReader.<init>(BytecodeReadingParanamer.java:451)
    at com.thoughtworks.paranamer.BytecodeReadingParanamer$ClassReader.<init>(BytecodeReadingParanamer.java:431)
    at com.thoughtworks.paranamer.BytecodeReadingParanamer$ClassReader.<init>(BytecodeReadingParanamer.java:492)
    at com.thoughtworks.paranamer.BytecodeReadingParanamer$ClassReader.<init>(BytecodeReadingParanamer.java:337)
    at com.thoughtworks.paranamer.BytecodeReadingParanamer.lookupParameterNames(BytecodeReadingParanamer.java:100)
    at com.thoughtworks.paranamer.CachingParanamer.lookupParameterNames(CachingParanamer.java:75)
    at com.thoughtworks.paranamer.CachingParanamer.lookupParameterNames(CachingParanamer.java:68)
    at net.liftweb.json.Meta$ParanamerReader$.lookupParameterNames(Meta.scala:89)
    at net.liftweb.json.Meta$Reflection$.argsInfo$1(Meta.scala:237)
    at net.liftweb.json.Meta$Reflection$.constructorArgs(Meta.scala:253)
    at net.liftweb.json.Meta$Reflection$.net$liftweb$json$Meta$Reflection$$findMostComprehensive$1(Meta.scala:266)
    at net.liftweb.json.Meta$Reflection$$anonfun$primaryConstructorArgs$1.apply(Meta.scala:269)
    at net.liftweb.json.Meta$Reflection$$anonfun$primaryConstructorArgs$1.apply(Meta.scala:269)
    at net.liftweb.json.Meta$Memo.memoize(Meta.scala:199)
    at net.liftweb.json.Meta$Reflection$.primaryConstructorArgs(Meta.scala:269)
    at net.liftweb.json.Extraction$.decompose(Extraction.scala:88)
    at net.liftweb.json.Extraction$$anonfun$1.applyOrElse(Extraction.scala:91)
    at net.liftweb.json.Extraction$$anonfun$1.applyOrElse(Extraction.scala:89)
    at scala.collection.immutable.List.collect(List.scala:305)
    at net.liftweb.json.Extraction$.decompose(Extraction.scala:89)
    at net.liftweb.json.Serialization$.write(Serialization.scala:38)
    at TestActor$.delayedEndpoint$TestActor$1(TestActor.scala:437)
    at TestActor$delayedInit$body.apply(TestActor.scala:54)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:383)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at TestActor$.main(TestActor.scala:54)
    at TestActor.main(TestActor.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)

如果我从case类中删除dateTime参数,它可以正常工作。似乎问题出在dateTime。

1 个答案:

答案 0 :(得分:0)

我在我的Intellij Idea上运行了你的代码,得到了同样的错误。试图调试原因,但调用堆栈是如此之深,我终于放弃了。 但我想也许是因为Lift没有提供LocaleDateTime的默认格式,就像你提到的帖子所说的那样,“默认情况下,它是Lift使用的DateParser格式。”

以下是供您参考的折衷方案,Lift-JSON为我们提供默认的日期格式

// net.liftweb.json.Serialization Line 72
def formats(hints: TypeHints) = new Formats {
  val dateFormat = DefaultFormats.lossless.dateFormat
  override val typeHints = hints
}

因此,我们不是一直编写自定义序列化程序,而是可以更改我们的数据类型以适应默认的日期格式。另外,net.liftweb.mongodb.DateSerializer(第79行)提供了对日期序列化的支持。

然后,我们可以提供方法来轻松获取LocaleDateTime。以下是我试图解决的问题。

package jacoffee.scalabasic

import java.time.{ ZoneId, LocalDateTime }
import java.util.Date

// package object defined is for Scala compiler to look for implicit conversion for case class parameter date
package object stackoverflow {
 implicit def toDate(ldt: LocalDateTime): Date =
   Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant())

 implicit def toLDT(date: Date): LocalDateTime =
   LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault())
}


package jacoffee.scalabasic.stackoverflow

import java.time.LocalDateTime
import java.util.Date
import net.liftweb.json.{ NoTypeHints, Serialization }
import net.liftweb.json.Serialization.{ read, write }


case class Child(var str: String, var Num: Int, var abc: Option[String],
 myList: List[Int], val date : Date = LocalDateTime.now()) {
   def getLDT: LocalDateTime = date
 }

object DateTimeSerialization extends App {
   implicit val formats = Serialization.formats(NoTypeHints)

   val ser = write(Child("Mary", 5, None, List(1, 2)))
// Child class converted to string {"str":"Mary","Num":5,"myList":[1,2],"date":"2015-07-21T03:07:05.699Z"}
   println(" Child class converted to string " + ser)

   var obj=read[Child](ser)
   // Object of Child is Child(Mary,5,None,List(1, 2),Tue Jul 21 11:48:22 CST 2015)
   println(" Object of Child is "+ obj)
   // LocalDateTime of Child is 2015-07-21T11:48:22.075
   println(" LocalDateTime of Child is "+ obj.getLDT)
}

无论如何,希望它有所帮助。