json4s序列化和反序列化泛型类型

时间:2016-10-06 16:46:16

标签: scala

因为我正在处理泛型类型,所以我不能使用特定的case类。然后我创建了一个泛型util,它序列化和反序列化泛型对象。

import org.json4s
import org.json4s.Formats._
import org.json4s.native.JsonMethods._

object JsonHelper {
  def json2Object[O](input: String) : O = {
    parse(json4s.string2JsonInput(input)).asInstanceOf[O]
  }
  def object2Json[O](input: O) : String = {
    write(input).toString
  }
}

编译器抛出错误:

  

找不到类型O的JSON序列化程序。尝试为此类型实现隐式Writer或JsonFormat。       写(输入)的ToString

这应该在运行时抛出,但为什么在编译时抛出它?

3 个答案:

答案 0 :(得分:8)

在上面的评论中,你问过“所以杰克逊如何使用java对象?它使用反射权吗?为什么它与Scala不同?”,这是这个问题的核心。

您导入的json4s“native”序列化程序使用编译时反射来创建Writer

杰克逊使用运行时反射来做同样的事情。

编译时版本效率更高;运行时版本更灵活。

要使用编译时版本,您需要让编译器有足够的信息根据要序列化的对象的声明类型选择正确的Writer。这将排除非常通用的编写器方法,如您提出的方法。请参阅@TimP关于如何修复该版本代码的答案。

要使用运行时版本,您可以通过org.json4s.jackson.JsonMethods._包使用Jackson。见https://github.com/json4s/json4s#jackson

答案 1 :(得分:5)

您发布的编译器错误来自 json4s代码中的这个位置。您正在调用的 write 函数采用隐式JSON Writer ,这是该方法可以采用任意类型的方式。它在编译时被捕获,因为隐式参数的编译方式与显式参数相同 - 就好像你有:




  def f(a:Int,b) :Int)= a + b
 f(5)//传递了错误数量的参数
  




我有一点点难以确切地看到你在这里调用的 write 方法 - json4s库非常大而且事情已经过载了。你可以粘贴你正在使用的声明的 write 方法吗?它几乎肯定有这样的签名:




  def write [T](value:T)(隐式编写者:Writer [T]):JValue&#xA ;  




如果它如上所示,请尝试在方法中包含隐式writer参数:


&#xA ;
  object JsonHelper {
 def json2Object [O](input:String)(隐式读者:Reader [O]):O = {
解析(json4s.string2JsonInput(输入))asInstanceOf [O]&#XA。 }
 def object2Json [O](输入:O)(隐式编写器:Writer [O]):String = {
写(输入)的ToString
 }
}
  



答案 2 :(得分:1)

在这个示例中,您处理泛型类型,Scala与其他jvm语言一样,在编译时具有type erasing机制(编译时的错误消息可能不包含有关泛型的消息) ,请尝试将此片段附加到两种方法的签名中:

(implicit tag: ClassTag[T])

it's类似于你的例子与通用,但与杰克逊。 HTH