如何在Scala中创建通用的JSON序列化器/反序列化器?

时间:2017-11-22 03:31:51

标签: scala generics jackson json4s

我想序列化和反序列化一些案例类,并意识到我在重复代码。不幸的是,我无法找到一种方法来保持干燥。希望有人可以提供一些帮助。下面我将提供一个不是DRY的示例问题。

示例问题

import org.json4s.jackson.Serialization

import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter

import org.json4s.JsonAST.JString
import org.json4s.{CustomSerializer, DefaultFormats}


case class Bar(bar: String, date: ZonedDateTime)
case class Foo(foo: String)

trait JsonParser {
  private case object ZDTSerializer extends CustomSerializer[ZonedDateTime](_ => (
    { case JString(s) => ZonedDateTime.parse(s) },
    { case zdt: ZonedDateTime => JString(zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"))) }
  ))

  implicit val formats = DefaultFormats + ZDTSerializer
}

object BarParser extends JsonParser {
  def deserialize(jsonBar: String): Bar = {
    Serialization.read[Bar](jsonBar)
  }

  def serialize(bar: Bar): String = {
    Serialization.write[Bar](bar)
  }
}

object FooParser extends JsonParser {
  def deserialize(jsonFoo: String): Foo = {
    Serialization.read[Foo](jsonFoo)
  }

  def serialize(foo: Foo): String = {
    Serialization.write[Foo](foo)
  }
}



object Main {
  def main(args: Array[String]): Unit = {
    val foo = Foo("foo")
    println(FooParser.serialize(foo)) // {"foo":"foo"}
    println(FooParser.deserialize(FooParser.serialize(foo))) // Foo(foo)
  }
}

上面很清楚,重复序列化和反序列化的逻辑。这是我尝试过的事情之一(不编译)。

尝试解决

case class Bar(product: String, date: ZonedDateTime)
case class Foo(title: String)

abstract class GenericJsonParser[T] {
  private case object ZDTSerializer extends CustomSerializer[ZonedDateTime](_ => (
    { case JString(s) => ZonedDateTime.parse(s) },
    { case zdt: ZonedDateTime => JString(zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"))) }
  ))

  implicit val formats = DefaultFormats + ZDTSerializer

  def deserialize(json: String): T = {
    Serialization.read[T](json)  // No Manifest available for T
  }

  def serialize(thing: T): String = {
    Serialization.write[T](thing) // type arguments [A] conform to the bounds of none of the overloaded alternatives ...
  }
}

object BarJsonParser extends GenericJsonParser[Bar]

object FooParser extends GenericJsonParser[Foo]

任何指导都将不胜感激。

1 个答案:

答案 0 :(得分:0)

我认为您可以使用Json.format [ACaseClass],例如:

import play.api.libs.json.{Format, Json}
case class ACaseClass(value: String, anotherValue: Int)
implicit val formatACaseClass = Json.format[ACaseClass]

我猜对于Seralization.read并写入你仍然要传递一个隐含值,jvm需要知道如何读/写你的对象/