如何检索构造函数参数的默认值?

时间:2014-05-06 20:26:09

标签: json scala playframework-2.0

我正在生成一组方法,这些方法将从Play JsObject中实例化一个类,例如

class Clazz(val1: Int = 1, val2: String, val3: Option[Int])

def createFromJson(json: JsObject) {
  Clazz((json \ "val1").as[Int], (json \ "val2").as[String], (json \ "val3").as[Option[Int]])
}

我们的几个类有超过22个字段,因此使用默认的Writes / Formats来执行此操作是不可行的(无论如何,默认值问题仍然存在)。

我希望能够说出,例如(json \ "val1").asOpt[Int].getOrElse(1)表示具有默认值的参数。我可以使用所有类的默认值创建一个val defaultValues: Map[String, JsValue]变量,或者我可以创建一个与输入json合并的val defaultValues: JsObject,但理想情况下我希望能够提取默认值直接来自类,否则我们将不可避免地更新构造函数的默认值,但不会更新defaultValues变量的默认值,反之亦然。

有办法做到这一点吗?

2 个答案:

答案 0 :(得分:3)

总有办法:)

"拉出班级的默认值"对我来说听起来像运行时反射工作或宏观工作 - 如果你没有任何先前的经验,这也不是一项简单的任务。

这里似乎有一个反思解决方案,你可以适应:How do I access default parameter values via Scala reflection?

但这会影响运行时性能,并可能影响预期的反序列化速度。

我建议使用defaultValues地图并在处理默认值逻辑的配对对象上创建apply方法。它将完成工作。

答案 1 :(得分:0)

我建议你在scala 2.11上使用case类:不再有22个字段的限制。 你可以通过宏或反射来做到这一点。 可以使用模块上的apply $ default $来访问成员的默认值。

这是一个示例代码,它提取默认值并返回[String,Any]默认值的映射。

  def getDefault[T](c: Context)(T: c.WeakTypeTag[T]): c.Expr[Map[String, Any]] = {
    import c.universe._
    val classSym = T.tpe.typeSymbol
    val moduleSym = classSym.companionSymbol
    val apply = moduleSym.typeSignature.declaration(newTermName("apply")).asMethod
    // can handle only default parameters from the first parameter list
    // because subsequent parameter lists might depend on previous parameters
    val kvps = apply.paramss.head.map(_.asTerm).zipWithIndex.flatMap {
      case (p, i) =>
        if (!p.isParamWithDefault) None
        else {
          val getterName = newTermName("apply$default$" + (i + 1))
          Some(q"${p.name.toString} -> $moduleSym.$getterName")
        }
    }
    c.Expr[Map[String, Any]](q"Map[String, Any](..$kvps)")
  }

请注意您的示例代码a" new"不见了。

您好,   阿尔贝托