【问题标题】:Is it possible in Play 2.1 to convert a JsValue to a case class instance if you only know the name of the case class at the runtime?如果您在运行时只知道案例类的名称,是否可以在 Play 2.1 中将 JsValue 转换为案例类实例?
【发布时间】:2013-07-05 17:59:40
【问题描述】:

我正在 Play 2.1 中构建 JSON RPC。为了调用正确的方法,RPC 调度程序使用反射来创建并按名称调用类方法实例。

现在一个 RPC 方法看起来像这样:

  def create(obj: JsValue) = {
    val menu: Menu = Json.fromJson[Menu](obj).get
    collection.insert(menu).map( r => toDirectResult(r))
  }

  def createCustom(obj: JsValue) = {
    val menu: Menu = Json.fromJson(obj)(Menu.customFormat).get
    collection.insert(menu).map( r => toDirectResult(r))
  }

我想做的是能够像这样定义 RPC 方法:

  def create(menu: Menu) = {
    collection.insert(menu).map( r => toDirectResult(r))
  }

问题在于 RPC 调度程序仅在运行时知道必须在名为“Menus”的类上调用名为“create”的方法,并且它具有作为 JsValue 传递给该方法的参数值。通过反射,我可以找出 RPC 方法的参数数量及其类型。当参数类型为case类时,如何使用case类的伴随对象中定义的隐式Formatter(或Reader)将JsValue转化为case类实例?

对于 createCustom 方法,我意识到没有“神奇”的解决方案,但是自从我开始学习 Scala 后,我发现用这种编程语言几乎没有什么是真正不可能的。是否可以使用注释或类似的东西来指定非隐式的格式化程序?

【问题讨论】:

    标签: scala reflection playframework playframework-2.1 scala-2.10


    【解决方案1】:

    【讨论】:

    • 不幸的是,这行不通。 RPC 方法不是控制器内部的操作,无法将它们映射到路由。我正在做的是ExtDirect 的实现,因此客户端只调用一个 URL,其他所有内容都以 JSON 形式发布。
    【解决方案2】:

    经过进一步仔细考虑,我认为反射确实不是解决我问题的正确方法。它在编译时缺乏类型安全和适当的错误报告,更难调试并且对性能也有影响。而且我实际上拥有在构建时生成代码所需的所有信息。

    不幸的是,我无法使用 Play 路由器,因为对于 JSON RPC 调度程序,路由取决于请求正文,而在 Play 路由期间不可用。但本质上,RPC 调度程序与 Play 路由器做同样的事情。所以目前我只是要手动编写我的 RPC 路由,然后问题中的问题就解决了。将来我打算编写一个 SBT 插件,它会自动生成调度程序代码,类似于 Play 路由器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-07
      • 2013-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-05
      相关资源
      最近更新 更多