哪个 JSON 序列化库适合以下情况?

发布于 2024-10-14 01:56:21 字数 208 浏览 1 评论 0原文

我有以下案例: 我想序列化使用 java.util.UUID 类型的 var 扩展父类的 Scala 案例类。 此案例类的序列化应该在没有任何配置的情况下进行 - 没有注释和自定义格式的定义。任何序列化提示都可以位于父类中。

我尝试了 sjson,但是基于反射的序列化无法序列化 UUID 类型,并且基于类型的序列化迫使我为每个案例类定义格式。 哪个 json 序列化库最适合这种情况?

I've got following case:
I'd like to serialize Scala case classes that extend parent class with var of type java.util.UUID.
Serialization of this case classes should happen without any configuration of them - no annotations and definition of custom formats. Any serialization hints may be situated in parent class.

I tried sjson, but Reflection based serialization can't serialize UUID types and type based serialization forces me to define formats for every case class.
Which json serialization library would best fit this case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

清音悠歌 2024-10-21 01:56:21

这是一种使用 Lift JSON 的解决方案。

import java.util.UUID
import net.liftweb.json._
import net.liftweb.json.JsonAST._
import net.liftweb.json.JsonDSL._
import net.liftweb.json.Serialization._

sealed abstract class Parent {
  def uuid: UUID
}
case class Foo(uuid: UUID, name: String) extends Parent

object UUIDTest extends Application {
  implicit val formats =  Serialization.formats(NoTypeHints) + new UUIDSerializer

  val f = Foo(UUID.randomUUID, "foo")
  val ser = write(f)
  println(ser)
  val f2 = read[Foo](ser)
  assert(f == f2)

  // Special serializer for UUID type
  class UUIDSerializer extends Serializer[UUID] {
    private val Class = classOf[UUID]

    def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), UUID] = {
      case (TypeInfo(Class, _), json) => json match {
        case JObject(JField("mostSig", JInt(m)) :: JField("leastSig", JInt(l)) :: Nil) =>
          new UUID(m.longValue, l.longValue)
        case x => throw new MappingException("Can't convert " + x + " to UUID")
      }
    }

    def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
      case x: UUID =>
        ("mostSig" -> x.getMostSignificantBits) ~ ("leastSig" -> x.getLeastSignificantBits)
    }
  }
}

它打印:

{"uuid":{"mostSig":-8054689529719995935,"leastSig":-5722404370736228056},"name":"foo"}'

另一种解决方案,它使用父类型的自定义序列化程序。

sealed abstract class Parent {
  var uuid: UUID = UUID.randomUUID
}
case class Foo(name: String) extends Parent

object UUIDTest extends Application {
  implicit val formats = 
    Serialization.formats(NoTypeHints) + new ParentSerializer

  val f = Foo("foo")
  val ser = write(f)
  println(ser)
  val f2 = read[Foo](ser)
  assert(f == f2)

  // Special serializer for Parent type
  class ParentSerializer extends Serializer[Parent] {
    def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), Parent] = {
      case (t@TypeInfo(cl, _), json) if (classOf[Parent].isAssignableFrom(cl)) => 
        val x = Extraction.extract(json, t)(DefaultFormats).asInstanceOf[Parent]
        x.uuid = (for { 
          JField("mostSig", JInt(m))  <- json
          JField("leastSig", JInt(l)) <- json 
        } yield new UUID(m.longValue, l.longValue)).head
        x
    }

    def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
      case x: Parent =>
        Extraction.decompose(x)(DefaultFormats) ++ 
        JField("mostSig", x.uuid.getMostSignificantBits) ++ 
        JField("leastSig", x.uuid.getLeastSignificantBits)
    }
  }
}

Here's one solution with Lift JSON.

import java.util.UUID
import net.liftweb.json._
import net.liftweb.json.JsonAST._
import net.liftweb.json.JsonDSL._
import net.liftweb.json.Serialization._

sealed abstract class Parent {
  def uuid: UUID
}
case class Foo(uuid: UUID, name: String) extends Parent

object UUIDTest extends Application {
  implicit val formats =  Serialization.formats(NoTypeHints) + new UUIDSerializer

  val f = Foo(UUID.randomUUID, "foo")
  val ser = write(f)
  println(ser)
  val f2 = read[Foo](ser)
  assert(f == f2)

  // Special serializer for UUID type
  class UUIDSerializer extends Serializer[UUID] {
    private val Class = classOf[UUID]

    def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), UUID] = {
      case (TypeInfo(Class, _), json) => json match {
        case JObject(JField("mostSig", JInt(m)) :: JField("leastSig", JInt(l)) :: Nil) =>
          new UUID(m.longValue, l.longValue)
        case x => throw new MappingException("Can't convert " + x + " to UUID")
      }
    }

    def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
      case x: UUID =>
        ("mostSig" -> x.getMostSignificantBits) ~ ("leastSig" -> x.getLeastSignificantBits)
    }
  }
}

It prints:

{"uuid":{"mostSig":-8054689529719995935,"leastSig":-5722404370736228056},"name":"foo"}'

Another solution which uses a custom serializer for Parent type.

sealed abstract class Parent {
  var uuid: UUID = UUID.randomUUID
}
case class Foo(name: String) extends Parent

object UUIDTest extends Application {
  implicit val formats = 
    Serialization.formats(NoTypeHints) + new ParentSerializer

  val f = Foo("foo")
  val ser = write(f)
  println(ser)
  val f2 = read[Foo](ser)
  assert(f == f2)

  // Special serializer for Parent type
  class ParentSerializer extends Serializer[Parent] {
    def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), Parent] = {
      case (t@TypeInfo(cl, _), json) if (classOf[Parent].isAssignableFrom(cl)) => 
        val x = Extraction.extract(json, t)(DefaultFormats).asInstanceOf[Parent]
        x.uuid = (for { 
          JField("mostSig", JInt(m))  <- json
          JField("leastSig", JInt(l)) <- json 
        } yield new UUID(m.longValue, l.longValue)).head
        x
    }

    def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
      case x: Parent =>
        Extraction.decompose(x)(DefaultFormats) ++ 
        JField("mostSig", x.uuid.getMostSignificantBits) ++ 
        JField("leastSig", x.uuid.getLeastSignificantBits)
    }
  }
}
遗弃M 2024-10-21 01:56:21

如果类型很重要,您应该查看 YAML。

http://www.google.fr/search?q=java+yaml

它是 json 的一个子集,具有改进的功能,例如变量类型。

If the type is important, you should take a look at YAML.

http://www.google.fr/search?q=java+yaml

It's a subset of json with improved stuff, like variable typing.

寻梦旅人 2024-10-21 01:56:21

你可以尝试 jerkson: https://github.com/codahale/jerkson

它对我的使用效果很好,但这主要是列表/映射结构。如果它支持您的需求,也不会感到惊讶。

编辑:尝试使用以下示例(受到另一个答案中的电梯示例的启发)。似乎工作正常。

import java.util.UUID
import com.codahale.jerkson.Json
import org.scalatest.FunSuite

sealed abstract class Parent {
   def uuid: UUID
}

case class Foo(uuid: UUID, name: String) extends Parent

class TmpJsonTest extends FunSuite {
   test("Json case class serialize") {
      val f = Foo(UUID.randomUUID, "foo")
      val ser = Json.generate(f)
      println(ser)
      val f2 = Json.parse[Foo](ser)
      assert(f === f2)
   }
}

You could try jerkson: https://github.com/codahale/jerkson

Its working good for my use, but that is mostly list/map structures. Would not be surprised if it supports your needs though..

Edit: Tried it with the following example (inspired by the lift example in another answer). Seems to work fine.

import java.util.UUID
import com.codahale.jerkson.Json
import org.scalatest.FunSuite

sealed abstract class Parent {
   def uuid: UUID
}

case class Foo(uuid: UUID, name: String) extends Parent

class TmpJsonTest extends FunSuite {
   test("Json case class serialize") {
      val f = Foo(UUID.randomUUID, "foo")
      val ser = Json.generate(f)
      println(ser)
      val f2 = Json.parse[Foo](ser)
      assert(f === f2)
   }
}
绅刃 2024-10-21 01:56:21

尝试使用包含 JSON 支持的 XStream 库。我已经在几个项目中成功地使用了它。它有许多默认转换器,其中包括一个用于 java.util.UUID 的转换器。默认转换器的完整列表位于此处:http://x-stream.github.io/converters .html

有关使用 XStream 进行 JSON 读写的简要教程位于:http://x- Stream.github.io/json-tutorial.html。本教程代码是为 Java 编写的,但它对于 Scala 的工作原理应该是相同的,因为反射是在幕后使用的。

请记住,使用此库并不总是可以序列化然后反序列化任意对象图。特别是,无法处理数据中的循环,即您的数据必须是纯粹的分层树。考虑到 JSON 格式的意图,这是一个合理的限制。

参考链接:
XStream JSON 教程: http://x-stream.github.io/json-tutorial.html
XStream 默认转换器: http://x-stream.github.io/converters.html

Try the XStream library which includes JSON support. I have used this successfully in a few projects. It has a number of default converters, including one for java.util.UUID. A full list of default converters is located here: http://x-stream.github.io/converters.html.

A brief tutorial on using XStream for JSON reading and writing is located here: http://x-stream.github.io/json-tutorial.html. The tutorial code is written for Java but it should work just the same for Scala since reflection is being used behind the scenes.

Keep in mind that serializing and then deserializing arbitrary graphs of objects is not always possible with this library. In particular, loops in your data cannot be handled, i.e. your data must be a purely hierarchical tree. This is a reasonable limitation given the intentions of the JSON format.

Referenced links:
XStream JSON tutorial: http://x-stream.github.io/json-tutorial.html
XStream default converters: http://x-stream.github.io/converters.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文