2015-06-14 93 views
0

我有一个类,在其构造需要几个可选Enumeration类型:如何使用特定的隐含的Json`reads`申请方法从斯卡拉

case class GPMedia(id: Option[GPID], created: Option[DateTime], active: Option[Boolean], data: Array[Byte], mimeType: Option[GPMediaType.Type], encoding: Option[GPEncoder.Codec], compression: Option[GPCompressor.Type]) 

我一直在努力创造一个implicit Json reads方法作品。我一直在结束了错误,如:

[error] /Users/zbeckman/Projects/Glimpulse/Server/project/glimpulse-server/app/utility/GPMedia.scala:57: overloaded method value apply with alternatives: 
etc... 

我试图做的是转换入的Json字符串,把他们变成了一种权利Option实例(例如,MIME类型为“图像/ PNG “在JSON会变成Option(GPMediaType(v))该GPMediaType构造将映射字符串,并返回一个正确的值(其中之一是GPMediaType.Unknown)。

这里的implicit reads是我到目前为止工作了,在GPMedia实施类'同伴对象...

case object GPMedia extends GPRequestLogging { 
    implicit val reads: Reads[GPMedia] = (
     (__ \ "id").readNullable[GPID] and 
      (__ \ "created").readNullable[DateTime] and 
      (__ \ "active").readNullable[Boolean] and 
      (__ \ "data").read[Array[Byte]] and 
      (__ \ "mimeType").readNullable[String].map(v => Option(GPMediaType(v))) and 
      (__ \ "encoding").readNullable[String].map(v => Option(GPEncoder(v.get))) and 
      (__ \ "compression").readNullable[String].map(v => Option(GPCompressor(v.get))) 
     )(GPMedia.apply _) 
} 

这是有效的,但是当我尝试添加其他apply()方法时,一切都很顺利。如何在Json reads实施中申请特定申请方法?例如,当我添加此apply方法:

def apply(data: Array[Byte]) = new GPMedia(None, None, None, data, None, None, None) 

我结束了:

[error] /Users/zbeckman/Projects/Glimpulse/Server/project/glimpulse-server/app/utility/GPMedia.scala:60: ambiguous reference to overloaded definition, 
[error] both method apply in object GPMedia of type (id: Option[models.GPID], created: Option[org.joda.time.DateTime], active: Option[Boolean], data: Array[Byte], mimeType: Option[utility.GPMediaType.Type], encoding: Option[utility.GPEncoder.Codec], compression: Option[utility.GPCompressor.Type])utility.GPMedia 
[error] and method apply in object GPMedia of type (data: Array[Byte])utility.GPMedia 
[error] match expected type ? 
[error]  )(GPMedia.apply _) 

我已经尝试了几种不同的方法,如(GPMedia.apply(...)),但我似乎无法得到参数正确。

我是新来的整个JSON隐式读者/作家和JSON解码语法。显然,我在这里失踪的东西...

编辑

这里是另外一个例子,关于我的尝试调用特定apply方法:

implicit val reads: Reads[GPMedia] = (
    (__ \ "id").readNullable[GPID] and 
     (__ \ "created").readNullable[DateTime] and 
     (__ \ "active").readNullable[Boolean] and 
     (__ \ "data").read[Array[Byte]] and 
     (__ \ "mimeType").readNullable[String].map(v => Option(GPMediaType(v))) and 
     (__ \ "encoding").readNullable[String].map(v => Option(GPEncoder(v.get))) and 
     (__ \ "compression").readNullable[String].map(v => Option(GPCompressor(v.get))) 
    )(v => GPMedia.apply(v.id, v.created, v.active, v.data, v.mimeType, v.encoding, v.compression)) 

这导致:

[error] /Users/zbeckman/Projects/Glimpulse/Server/project/glimpulse-server/app/utility/GPMedia.scala:60: type mismatch; 
[error] found : utility.GPMedia 
[error] required: (Option[models.GPID], Option[org.joda.time.DateTime], Option[Boolean], Array[Byte], Option[utility.GPMediaType.Value], Option[utility.GPEncoder.Value], Option[utility.GPCompressor.Type]) 
[error]  (which expands to) (Option[models.GPID], Option[org.joda.time.DateTime], Option[Boolean], Array[Byte], Option[utility.GPMediaType.Value], Option[utility.GPEncoder.Value], Option[utility.GPCompressor.Value]) 
[error]  )(v => GPMedia.apply(v.id, v.created, v.active, v.data, v.mimeType, v.encoding, v.compression)) 
[error]       ^
+0

是不是可以重新命名你的应用函数并从读取中调用它? – Biswanath

+0

是的,但重点是,我想在整个代码中应用()'方法,以便我们不必使用'new'和一些非Scala语法...... – Zac

回答

1

这是不可能的。编译器不知道使用哪个apply方法。这只是使用重载方法的一个注意事项。你可以使这个“很好”的唯一方法是重命名这些方法,或者用不同的名称替换重载的方法,然后使用这些方法。


你的第二个尝试不起作用,因为编译器期待一个函数来apply类似的签名,如:

(Option[GPID], Option[DateTime], Option[Boolean], Array[Byte], Option[String], Option[String], Option[String]) => GPMedia 

但你正在尝试使用:

GPMedia => GPMedia 

这不起作用,因为我们还没有GPMedia对象,只有tupled字段。它看起来更像:

implicit val reads: Reads[GPMedia] = (
    (__ \ "id").readNullable[GPID] and 
    (__ \ "created").readNullable[DateTime] and 
    (__ \ "active").readNullable[Boolean] and 
    (__ \ "data").read[Array[Byte]] and 
    (__ \ "mimeType").readNullable[String].map(v => Option(GPMediaType(v))) and 
    (__ \ "encoding").readNullable[String].map(v => Option(GPEncoder(v.get))) and 
    (__ \ "compression").readNullable[String].map(v => Option(GPCompressor(v.get))) 
).tupled.map(v => GPMedia.apply(v._1, v._2, v._3, v._4, v._5, v._6, v._7)) 

这看起来不太好。通常我们可以使它看起来像这更好:

implicit val reads: Reads[GPMedia] = (
    (__ \ "id").readNullable[GPID] and 
    (__ \ "created").readNullable[DateTime] and 
    (__ \ "active").readNullable[Boolean] and 
    (__ \ "data").read[Array[Byte]] and 
    (__ \ "mimeType").readNullable[String].map(v => Option(GPMediaType(v))) and 
    (__ \ "encoding").readNullable[String].map(v => Option(GPEncoder(v.get))) and 
    (__ \ "compression").readNullable[String].map(v => Option(GPCompressor(v.get))) 
).tupled.map(v => GPMedia.apply _ tupled v) 

除了,你最终会与你开始了同样的问题,因为编译器将无法选择正确的方法apply。所以你别无选择,只能重新命名或让事情变得丑陋。

+0

谢谢 - 那个确实有很大的帮助。我甚至不会想到,我可以使用完全不同的方法,而不是“应用”,这是有道理的。我想我会试试看。真正的目标是允许“公共API”拥有一组好的构造函数(意思是“应用”方法)......如果我能找到一种方法来获得所有隐式读/写,并且Slick能够存活,我认为我们会保持良好状态。 – Zac

1

这是可能的。

但是,您需要指定重载应用方法using _: ParameterType所需的所有参数,就像我在下面所做的那样,它将起作用。

implicit val reads: Reads[GPMedia] = (
    (__ \ "id").readNullable[GPID] and 
     (__ \ "created").readNullable[DateTime] and 
     (__ \ "active").readNullable[Boolean] and 
     (__ \ "data").read[Array[Byte]] and 
     (__ \ "mimeType").readNullable[String].map(v => Option(GPMediaType(v))) and 
     (__ \ "encoding").readNullable[String].map(v => Option(GPEncoder(v.get))) and 
     (__ \ "compression").readNullable[String].map(v => Option(GPCompressor(v.get))) 
    ) (
    v => GPMedia.apply(
     _: GPID, 
     _: DateTime, 
     _: Boolean, 
     _: Array[Byte], 
     _: Option[GPMediaType], 
     _: Option[GPEncoder], 
     _: Option[GPCompressor] 
    ) 
)