【问题标题】:Scala Gson, cannot serialize Option[Blob]Scala Gson,无法序列化 Option[Blob]
【发布时间】:2017-01-24 16:24:51
【问题描述】:

我设法扩展 Gson 以处理 Scala 的 OptionBlob 类型,但我对组合的 Option[java.sql.Blob] 有问题。

我的测试显示

[info] - 应该序列化一个 Option - OK

[info] - 应该序列化一个 Blob - OK

[info] - 应该序列化一个 Option[Blob] * FAILED *

[info] {"x":{"buf":[97,115,100,102],"len":4,"origLen":4}} 不等于 {"x":"asdf"}

你能告诉我这个{"buf": [...]} 对象是什么,可能为什么 Gson 会这样做吗? 我的序列化程序(如下)肯定告诉他用它创建一个字符串,但这个对象是甚至没有引用。

FWIW,尝试用真实 Blob 序列化具有 Option[Blob] 字段的真实对象(数据库行),我什至收到 StackOverflow 错误。

这是我编写序列化程序的方式:

class OptionSerializer extends JsonSerializer[Option[Any]] {
  def serialize(src: Option[Any], typeOfSrc: Type, context: JsonSerializationContext): JsonElement = {
    src match {
      case None => JsonNull.INSTANCE
      case Some(v) => context.serialize(v)
    }
  }
}

class BlobSerializer extends JsonSerializer[java.sql.Blob] {
  override def serialize(src: java.sql.Blob, typeOfSrc: Type, context: JsonSerializationContext): JsonElement = {
    val s: String = utils.blob2String(v)
    context.serialize(s)
  }
}

class BlobOptionSerializer extends JsonSerializer[Option[java.sql.Blob]] {
  override def serialize(src: Option[java.sql.Blob], typeOfSrc: Type, context: JsonSerializationContext): JsonElement = {
    src match {
      case None => JsonNull.INSTANCE
      case Some(v: java.sql.Blob) =>
        val s: String = utils.blob2String(v)
        context.serialize(s)
    }
  }
}

private val builder = new GsonBuilder()
builder.registerTypeAdapter(classOf[java.sql.Blob], new BlobSerializer)
builder.registerTypeAdapter(classOf[Option[java.sql.Blob]], new BlobOptionSerializer)
builder.registerTypeAdapter(classOf[Option[Any]], new OptionSerializer)
val gson = builder.create()

产生上述结果的测试:

case class B(x: Option[Int], y: String)
case class C(x: java.sql.Blob)
case class D(x: Option[java.sql.Blob])

"serialize options" in {
  val b = B(Some(1), "asdf")
  gson.toJson(b) must be ("{\"x\":1,\"y\":\"asdf\"}")
}

"serialize a Blob" in {
  val c = C(utils.string2Blob("asdf"))
  gson.toJson(c) must be ("{\"x\":\"asdf\"}")
}

"serialize an Option[Blob]" in {
  val d = D(Some(utils.string2Blob("asdf")))
  gson.toJson(d) must be ("{\"x\":\"asdf\"}")
}

还有我从 Blob 到 Blob 的转换方法,以防万一:

def string2Blob(s: String) = {
  new SerialBlob(s.getBytes)
}

def blob2String(blob: java.sql.Blob): String = {
  if (blob.length == 0)
    return ""  // Array[Byte]()
  val b: Array[Byte] = blob.getBytes(1, blob.length.toInt)
  blob.free
  new String(b)
}

【问题讨论】:

  • 我意识到如果我删除Option[Any] 的序列化程序,Option[Blob] 工作正常......所以它们有点“堆栈”,我可能需要一个用于Option[Any but Blob] 和一个用于Option[Blob].

标签: scala gson blob


【解决方案1】:

找到解决方案,在 Option[Any] 的序列化程序中对 Blob 类型进行特殊封装:

class OptionSerializer extends JsonSerializer[Option[Any]] {
  def serialize(src: Option[Any], typeOfSrc: Type, context: JsonSerializationContext): JsonElement = {
    src match {
      case None => JsonNull.INSTANCE
      case Some(b: java.sql.Blob) => context.serialize(utils.Sql.blob2String(b))
      case Some(v) => context.serialize(v)
    }
  }
}

【讨论】:

    猜你喜欢
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    • 2016-08-22
    • 2013-09-09
    相关资源
    最近更新 更多