问题描述
我有一个供Tuple使用的json序列化程序。它首先在Tuple上进行反思,并构建一个函数,该函数给定Tutu的一些元数据,它将返回(TypeAdapter,值)对的列表。 (TypeAdapter是一种特定于类型的东西,它呈现值。)如下所示:
def extractTuple(p: Product): (Product)=>List[(TypeAdapter[_],Any)] = {
val reflected = reflectOnTuple(tupleClass) // extract a bunch of reflected Metadata
val tupleFieldInfo = reflected.tupleFieldInfo
tupleFieldInfos match {
case 1 =>
(p: Product) =>
List( (getTypeAdapterFor(tupleFieldInfo(0)),p.asInstanceOf[Tuple1[_]]._1) )
case 2 =>
(p: Product) =>
List( (getTypeAdapterFor(tupleFieldInfo(0)),p.asInstanceOf[Tuple1[_]]._1),(getTypeAdapterFor(tupleFieldInfo(1)),p.asInstanceOf[Tuple1[_]]._2) )
//... and so on to Tuple23
}
}
在JSON序列化程序中,我有一个writeTuple()函数,如下所示。从理论上讲,它应该是按原样工作的,但是...我在fieldValue上遇到编译错误,说当期望值是1.T时,它的类型为Any。
TypeAdapter看起来像:
trait TypeAdapter[T] {
def write[WIRE](
t: T,writer: Writer[WIRE],out: mutable.Builder[WIRE,WIRE]): Unit
}
class JsonWriter() {
def writeTuple[T](t: T,writeFn: (Product) => List[(TypeAdapter[_],Any)],out: mutable.Builder[JSON,JSON]): Unit = {
out += "[".asInstanceOf[JSON]
var first = true
writeFn(t.asInstanceOf[Product]).foreach { case (fieldTA,fieldValue) =>
if (first)
first = false
else
out += ",".asInstanceOf[JSON]
fieldTA.write(fieldValue,this,out) // <<-- this blows up (compile) on fieldValue because it's type Any,not some specific field Type
}
out += "]".asInstanceOf[JSON]
}
}
如何使TypeAdapter确信该字段是正确的类型?
解决方法
尝试对类型变量tp
使用类型模式(小写)
class JsonWriter() extends Writer[JSON] {
def writeTuple[T](t: T,writeFn: (Product) => List[(TypeAdapter[_],Any)],out: mutable.Builder[JSON,JSON]): Unit = {
...
writeFn(t.asInstanceOf[Product]).foreach { case (fieldTA: TypeAdapter[tp],fieldValue) =>
...
fieldTA.write(fieldValue.asInstanceOf[tp],this,out)
}
...
}
}
或T
代替
class JsonWriter() extends Writer[JSON] {
def writeTuple[T](t: T,JSON]): Unit = {
...
writeFn(t.asInstanceOf[Product]).foreach { case (fieldTA: TypeAdapter[T],fieldValue) =>
...
fieldTA.write(fieldValue.asInstanceOf[T],out)
}
...
}
}
似乎您实际上并没有在T
中使用writeTuple[T]
。也许您可以尝试单态def writeTuple(t: Product...
,而且如果您要指定(TypeAdapter[_],Any)
实际上是(TypeAdapter[U],U)
且在元组的两个元素中都具有相同的U
,则可以尝试存在类型{{ 1}}。所以尝试
(TypeAdapter[U],U) forSome {type U}
,
Dmytro,您的答案非常接近!不幸的是,第一个或第二个选项均未编译。我认为3rd可以正常工作,除非...我实际上是在使用Dotty而不是Scala,并且Dotty消除了存在类型。
因此,我尝试了以下操作,并成功了。它知道它的类型,因此涉及修改TypeAdapter:
trait TypeAdapter[T] {
type tpe = T
def write[WIRE](
t: T,writer: Writer[WIRE],out: mutable.Builder[WIRE,WIRE]): Unit
inline def castAndWrite[WIRE](
v: Any,WIRE]): Unit =
write(v.asInstanceOf[tpe],writer,out)
}
从JsonWriter调用castAndWrite()可以调用正确类型的write()机制。