如何在Scala中解析JSON中的泛型类参数?

时间:2018-02-12 22:21:15

标签: java json scala generics json4s

我有一个通用的getter特质

trait Getter[A] {
  def get: A
}

我想将JSON解析为实现此特征的对象列表。两个这样的实现:

case class CoalesceGetter[A](getters: List[Getter[String]]) extends Getter[A] {
  override def get: A = getters.map(_.get).find(_ != null).orNull
}

case class AsnGetter(ipGetter: Getter[String]) extends Getter[Long] {
  override def get: Long = 99L // dummy function
}

我想基于名为Getter的属性将JSON解析为正确的function类,该属性对应于类,而type对应于getter情况下的泛型类型这需要一个泛型(两个属性都是我正在解析的json blob中的字符串)。我已经查看了json4s的自定义序列化程序,但没有看到如何使用泛型。任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:1)

首先,我不认为用类型参数对类进行jsonify是一个好主意。我认为定义与json对象直接等效的非类型(case)类是一种更好的设计,并使用许多库提供的标准读/写json。

然而,为了回答你的问题,我想回答另一个问题:你将如何做到这一点"手动"? 即你会如何用不同的A来编写和阅读不同的CoalesceGetter [A]?

这是一个命题:将类型arg放在json字段中:

"ofInt":   {"type-arg":"Int", "getters":[ ... list of getters in json ...]},
"ofDouble":{"type-arg":"Double", "getters":[ ... list of getters in json ...]}

现在,如果您要编写阅读器,您将如何实例化2 ofInt和ofDouble,知道类型-arg" Int"和" Double" (这是字符串!)。

我看到了两个解决方案:

1)你有一个arg-type string =>的硬编码地图实际的scala类型

 argType match{
   case "Int"    => new CoalesceGetter[Int](...)
   case "Double" => new CoalesceGetter[Double](...)
 }

2)或者在arg-type字符串中存储和读取通用类型作为字符串值,例如java Class.forName(例如,参见[https://stackoverflow.com/a/7495850/1206998])。但这是一个非常糟糕的主意恕我直言。

(注意:如果你想序列化任何对象只是为了稍后或在另一台计算机上重新加载它,不要使用json但是专用序列化,例如Java序列化或者spark使用的kryo)