隐式jsonFormat用于包含可变参数的case类

我有一个包含可变参数的case类,带有隐式jsonFormat,如下所示:

import spray.json._
case class Colors(name: String*)
object MyJsonProtocol extends DefaultJsonProtocol {
  implicit val colorFormat = jsonFormat1(Colors)
}
import MyJsonProtocol._
Colors("CadetBlue").toJson

它引发了一个错误:

error: type mismatch;
found   : Color2.type
required: Seq[String] => Color2
Note: implicit value colorFormat is not applicable here because it comes after the application point and it lacks an explicit result type
      implicit val colorFormat = jsonFormat1(Color2)
                                            ^

我也试过:

implicit val colorFormat = jsonFormat1(Colors.apply)

这导致了一个不同的(runtime!)异常:

java.lang.RuntimeException: Cannot automatically determine case class field names and order for 'Colors', please use the 'jsonFormat' overload with explicit field name specification

下列:

implicit val colorFormat = jsonFormat(Colors, "name")

引发了前一个错误

甚至有可能使用可变参数定义隐式jsonFormat的case类?


它应该完美地工作,可能你含糊不清。 这完美地工作:

import spray.json._, DefaultJsonProtocol._

case class Test(param: String*)
object Test {
  implicit val testFormat = jsonFormat1(Test.apply)
}

像最佳实践建议一样,不要使用协议模式,它会导致大型项目中的大型隐式错误,因此始终在协同对象中定义含义(因为存在异常情况)。 另一点避免继承,这不是真的需要。

Scala *模式只是Seq类型构造函数的一个糖,所以它应该为这种情况找到seqFormat (un)marshaller。

更新

它不起作用,因为Spray使用ClassManifestcopy函数中提取字段名称,但编译器不会在构造函数中使用可变长度类型为case类生成此函数:

case class Test(params: String*)
def man[A: ClassManifest] = implicitly[ClassManifest[A]]
man[Test].erasure.getDeclaredMethods.filter(_.getName.contains("copy"))
res4: Array[java.lang.reflect.Method] = Array()

scala> case class Test(param: String)
defined class Test

scala> man[Test].erasure.getDeclaredMethods.filter(_.getName.contains("copy"))
warning: there was one deprecation warning; re-run with -deprecation for details
res5: Array[java.lang.reflect.Method] = Array(public Test Test.copy(java.lang.String), public java.lang.String Test.copy$default$1())

所以你需要手动提供字段名称。 顺便说一句,我以前不知道这一点


我建议你用name: List[String]定义你的案例类name: List[String]并用自定义的apply函数创建伴侣对象。 您仍然可以创建Colors("blue", "green")

case class Colors(name: List[String])

object Colors {
  def apply(name: String*): Colors = new Colors(name.toList)
  def apply(names: List[String]): Colors = new Colors(names)
}


Colors("blue", "green")
链接地址: http://www.djcxy.com/p/78951.html

上一篇: Implicit jsonFormat for case class with varargs

下一篇: Java, 3 dots in parameters