[英]How to use specific apply method in implicit Json `reads` from Scala
我有一個在其構造函數中采用一些可選Enumeration
類型的類:
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
實例(例如,Json中的MIME類型“ image / png”將轉換為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方法? 例如,當我添加以下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] ^
有可能的。
但是您需要using _: ParameterType
來指定重載apply方法所需的所有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]
)
)
這是不可能的。 編譯器不知道使用哪種apply
方法。 這只是使用重載方法的警告之一。 像“ nice”這樣的唯一方法是重命名方法,或使用不同的名稱對重載的apply
方法進行別名並使用它們。
您的第二次嘗試不起作用,因為編譯器期望函數的簽名類似於apply
,例如:
(Option[GPID], Option[DateTime], Option[Boolean], Array[Byte], Option[String], Option[String], Option[String]) => GPMedia
但是您正在嘗試使用:
GPMedia => GPMedia
這行不通,因為我們還沒有GPMedia
對象,只有元組字段。 它看起來更像:
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
方法。 因此,您實際上別無選擇,只能重命名或使其變得丑陋。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.