标题其实没说明白,就是假设我有四个不同类型的对象:A,B,C,D 但是呢,我序列化的时候不知道这对象会是哪个,反序列化的时候也不知道应该用哪个进行反序列化。
因为我们知道一般Json 序列化反序列化是这样的:
object JsonUtils {
/** Used to convert between classes and JSON. */
val mapper = new ObjectMapper with ScalaObjectMapper
mapper.setSerializationInclusion(Include.NON_ABSENT)
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
mapper.registerModule(DefaultScalaModule)
def toJson[T: Manifest](obj: T): String = {
mapper.writeValueAsString(obj)
}
def toPrettyJson[T: Manifest](obj: T): String = {
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj)
}
def fromJson[T: Manifest](json: String): T = {
mapper.readValue[T](json)
}
}
也就是把json转化为对象或者对象转化为json都需要指定类型。但是有时候我们拿到一个json的时候,我并不知道是A,B,C,D的哪个一类型。
然后昨天在做Delta Compaction功能的时候,看到delta用了一个小技巧解决这个问题。 Delta有AddFile,RemoveFile,Metadata等对象。首先这些对象都继承一个父类:
sealed trait Action {
def wrap: SingleAction
def json: String = JsonUtils.toJson(wrap)
}
该父类做了一个序列化功能,首先会将自己wrap成一个SingleAction对象,然后在用json序列化SingleAction对象而不是直接序列化自己。
子类实现wrap也很简单:
override def wrap: SingleAction = SingleAction(add = this)
就是把自己传递给SingleAction. 那这样json序列化SingleAction的时候,同时也序列化了自己。
那SingleAction是啥样的呢?只是不同类型数据的枚举:
/** A serialization helper to create a common action envelope. */
case class SingleAction(
txn: SetTransaction = null,
add: AddFile = null,
remove: RemoveFile = null,
metaData: Metadata = null,
protocol: Protocol = null,
commitInfo: CommitInfo = null) {
def unwrap: Action = {
if (add != null) {
add
} else if (remove != null) {
remove
} else if (metaData != null) {
metaData
} else if (txn != null) {
txn
} else if (protocol != null) {
protocol
} else if (commitInfo != null) {
commitInfo
} else {
null
}
}
}
当我们反序列化的时候,得到的对象是确认的,就是SinlgeAction,因为SingleAction只会有一个值不为null,所以通过uwrap就得到具体的对象了。当然,唯一的缺憾是你需要通过isInstanceOf等判定下最后得到的对象是啥。