【问题标题】:json4s Serialize and deserialize generic typejson4s 序列化和反序列化泛型类型
【发布时间】:2016-11-01 14:18:37
【问题描述】:

因为我处理的是泛型类型,所以我不能使用特定的案例类。然后我创建了一个通用工具来序列化和反序列化通用对象。

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

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

【问题讨论】:

  • 在您的脑海中会发生怎样的变化?如果O 可以是任何东西,那么 json4s 如何知道在所有情况下该做什么?只要为 O 定义了 Writer 或 JsonFormat,您的 write(input) 就可以工作。在编译时找不到
  • @mfirry 那么 jackson 如何使用 java 对象呢?它使用反射对吗?为什么它与 Scala 不同?

标签: scala


【解决方案1】:

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

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

Jackson 使用运行时反射来做同样的事情。

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

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

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

【讨论】:

    【解决方案2】:

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

    def f(a: Int, b: Int) = a + b
    f(5) // passed the wrong number of arguments
    

    我很难确切地看到您在此处调用的 write 方法—— json4s 库非常大,而且内容超载。你能粘贴你正在使用的声明的write 方法吗?它几乎肯定有这样的签名:

    def write[T](value: T)(implicit writer: Writer[T]): JValue
    

    如果看起来像上面那样,请尝试在您的方法中包含隐式 writer 参数:

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

    【讨论】:

      【解决方案3】:

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

      (implicit tag: ClassTag[T])
      

      it's 与您的示例类似,但使用的是 jackson。 高温

      【讨论】:

        猜你喜欢
        • 2020-11-19
        • 1970-01-01
        • 1970-01-01
        • 2012-02-27
        • 2015-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-18
        相关资源
        最近更新 更多