2016-10-06 63 views
5

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

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 
    } 
} 

编译器会引发错误:

No JSON serializer found for type O. Try to implement an implicit Writer or JsonFormat for this type. write(input).toString

这将会在运行时抛出,但为什么它在编译时抛出的真实?

+0

事情如何在您的脑海中起作用?如果'O'可以是任何东西,那么json4s怎么知道在所有情况下要做什么?只要为O定义了Writer或者JsonFormat,你的'write(input)'就可以工作。在编译的时候,这个没有被发现 – mfirry

+1

@mfirry那么jackson如何使用java对象呢? 它使用反射权吗?为什么它与Scala不同? –

回答

7

在上面留言,你问“那么杰克森如何使用java对象?它使用反射权?它与Scala有什么不同?“,这是问题的核心。

已导入使用了编译时反射创建Writer的json4s“本地”串行。

杰克逊使用运行时反射来这样做。

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

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

要使用运行时版本,您可以通过org.json4s.jackson.JsonMethods._包中使用杰克逊。请参阅https://github.com/json4s/json4s#jackson

1

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

(implicit tag: ClassTag[T]) 

it's类似于您例如使用通用的,但与杰克逊。 HTH

5

您发布的编译器错误来自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 

如果它看起来像上述情况,尝试包括你的方法隐含作家参数为这样:

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 
    } 
}