【问题标题】:How to write a custom serializer for Java 8 LocalDateTime如何为 Java 8 LocalDateTime 编写自定义序列化程序
【发布时间】:2015-07-25 13:05:39
【问题描述】:

我有一个名为 Child1 的类,我想使用 Lift Json 将其转换为 JSON。一切正常我使用joda date time 但现在我想使用Java 8 LocalDateTime 但我无法为此编写自定义序列化程序这是我的代码

import org.joda.time.DateTime
import net.liftweb.json.Serialization.{ read, write }
import net.liftweb.json.DefaultFormats
import net.liftweb.json.Serializer
import net.liftweb.json.JsonAST._
import net.liftweb.json.Formats
import net.liftweb.json.TypeInfo
import net.liftweb.json.MappingException

class Child1Serializer extends Serializer[Child1] {
  private val IntervalClass = classOf[Child1]

  def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), Child1] = {
    case (TypeInfo(IntervalClass, _), json) => json match {
      case JObject(
        JField("str", JString(str)) :: JField("Num", JInt(num)) :: 
        JField("MyList", JArray(mylist)) :: (JField("myDate", JInt(mydate)) :: 
        JField("number", JInt(number)) ::Nil)
      ) => {
        val c = Child1(
          str, num.intValue(), mylist.map(_.values.toString.toInt), new DateTime(mydate.longValue)
        )
        c.number = number.intValue()
        c
      }
      case x => throw new MappingException("Can't convert " + x + " to Interval")
    }
  }

  def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
    case x: Child1 => 
      JObject(
        JField("str", JString(x.str)) :: JField("Num", JInt(x.Num)) ::
        JField("MyList", JArray(x.MyList.map(JInt(_)))) :: 
        JField("myDate", JInt(BigInt(x.myDate.getMillis))) :: 
        JField("number", JInt(x.number)) :: Nil
      )
  }
}

Object Test extends App {
  case class Child1(var str:String, var Num:Int, MyList:List[Int], myDate:DateTime) {
    var number: Int=555
  }
  val c = Child1("Mary", 5, List(1, 2), DateTime.now())
  c.number = 1
  println("number" + c.number)
  implicit val formats = DefaultFormats + new Child1Serializer
  val ser = write(c)
  println("Child class converted to string" + ser) 

  var obj = read[Child1](ser)
  println("object of Child is "+  obj)
  println("str" + obj.str)
  println("Num" + obj.Num)
  println("MyList" + obj.MyList)
  println("myDate" + obj.myDate)
  println("number" + obj.number)
}

现在我想像这样使用 Java 8 LocalDateTime

case class Child1(var str: String, var Num: Int, MyList: List[Int], val myDate: LocalDateTime = LocalDateTime.now()) {
  var number: Int=555
}

我需要在我的自定义序列化程序类中进行什么修改 Child1Serializer 我试图这样做但我无法做到,请帮助我

【问题讨论】:

    标签: java json scala scala-2.11 lift-json


    【解决方案1】:

    在序列化器中,像这样序列化日期:

    def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
    case x: Child1 => 
      JObject(
        JField("str", JString(x.str)) :: JField("Num", JInt(x.Num)) ::
        JField("MyList", JArray(x.MyList.map(JInt(_)))) :: 
        JField("myDate", JString(x.myDate.toString)) :: 
        JField("number", JInt(x.number)) :: Nil
      )
    

    }

    在反序列化器中,

    def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), Child1] = {
    case (TypeInfo(IntervalClass, _), json) => json match {
      case JObject(
        JField("str", JString(str)) :: JField("Num", JInt(num)) :: 
        JField("MyList", JArray(mylist)) :: (JField("myDate", JString(mydate)) :: 
        JField("number", JInt(number)) ::Nil)
      ) => {
        val c = Child1(
          str, num.intValue(), mylist.map(_.values.toString.toInt), LocalDateTime.parse(myDate)
        )
        c.number = number.intValue()
        c
      }
      case x => throw new MappingException("Can't convert " + x + " to Interval")
     }
    }
    

    LocalDateTime 对象使用toString 写入ISO 格式,parse 工厂方法应该能够从这样的字符串重构对象。

    【讨论】:

    • 子类转换为字符串{"str":"Mary","Num":5,"MyList":[1,2],"myDate":"2015-07-28T17:09 :31.512","number":1} [error] (run-main-1) net.liftweb.json.MappingException: 未知错误 net.liftweb.json.MappingException: net.liftweb.json.Extraction$ 处的未知错误。在 Net.liftweb.json.Serialization$.read(Serialization.scala:58) 在 MessageTest$.delayedEndpoint 在 net.liftweb.json.JsonAST$JValue.extract(JsonAST.scala:312) 处提取(Extraction.scala:46) $MessageTest$1(MessageTest.scala:58) 在 MessageTest$delayedInit$body.apply(MessageTest.scala:15)
    【解决方案2】:

    您可以像这样定义 LocalDateTime 序列化程序。

    class LocalDateTimeSerializer extends Serializer[LocalDateTime] {
      private val LocalDateTimeClass = classOf[LocalDateTime]
    
      def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), LocalDateTime] = {
        case (TypeInfo(LocalDateTimeClass, _), json) => json match {
          case JString(dt) =>  LocalDateTime.parse(dt)
          case x => throw new MappingException("Can't convert " + x + " to LocalDateTime")
        }
      }
    
      def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
        case x: LocalDateTime => JString(x.toString)
      }
    }
    

    也像这样定义你的格式

    implicit val formats = DefaultFormats + new LocalDateTimeSerializer + new FieldSerializer[Child1]
    

    请注意FieldSerializer的用法,序列化非构造函数字段,编号

    【讨论】:

    • 子类转换为字符串{"number":1,"str":"Mary","Num":5,"MyList":[1,2],"myDate":"2015 -07-28T16:45:44.030"} [错误] (run-main-2) net.liftweb.json.MappingException: 未知错误 net.liftweb.json.MappingException: net.liftweb.json.Extraction$ 的未知错误。在 Net.liftweb.json.Serialization$.read(Serialization.scala:58) 在 MessageTest$.delayedEndpoint 在 net.liftweb.json.JsonAST$JValue.extract(JsonAST.scala:312) 处提取(Extraction.scala:46) $MessageTest$1(MessageTest.scala:42))
    • 看起来像是 lift-json 使用的参数库的问题 - github.com/paul-hammant/paranamer/issues/17
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-12
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多