如何创建 Grails HAL 转换器

How to create a Grails HAL converter

我知道有一个 HalJsonRenderer,但我想知道是否有一种方法可以拥有类似 JSON 转换器的东西,以便能够执行以下操作:

render MyObject as HAL

"as" 运算符...它是如何工作的?

如果添加可选的括号,render ... as JSON 会更清楚:

render(foo as JSON)

render 方法有一些重载,其中之一接受 JSON,所以棘手的部分是 foo as JSON

Groovy 通过将每个运算符与实际执行工作的方法配对,使重载运算符变得简单。 == 运算符是通过调用 equals 方法实现的(或者 compareTo 如果 class 实现了 Comparable<< 运算符调用 leftShift, 等等 This archived page 有很好的 table 运算符及其相应的方法(Groovy 站点最近进行了重大检修,这个页面似乎在随机播放中丢失了)。

as 在技术上不是运算符,但它的处理方式类似。如果您添加一个 asType 方法,它将被调用以使 class 有机会将自身转换为请求的类型:

Object asType(Class c) { ... }

Grails 连接 as JSONas XML 的方式相当复杂,但重要的部分涉及向所有控制器添加 asType 方法(除了 render, redirect, getParams(以及相应的 params 属性)等)此方法然后转换为 JSON 或 XML ,或者如果目标 class 不是 JSON 或 XML.

,则执行传统的 cast/conversion

我认为直接支持它会比它值得做的更多工作,所以如果是我,我会在服务中创建一个方法来完成将支持的类型转换为 HAL 并呈现它的工作,比如

class SomeService {
   String asHal(foo) {
      ...
   }
}

然后你可以从你的控制器调用它:

class SomeController {

   def someService

   def anAction() {
      ...
      def foo = ...
      render someService.asHal(foo)
   }
}

这不像 render as HAL 那样方便,但它的工作量并不多,而且好处是不那么神奇。

要支持 render foo as HAL,您需要向任何 class foo 添加一个 asType 方法,或者做类似于 Grails 为 [=64 做的事情=] 和 XML。添加一个 asType 方法可能是不切实际的,特别是如果你想支持多种类型,如果这些类型像 ArrayList 一样预先存在 class 则更是如此。您可以像 JSON 和 XML class 那样实现 org.codehaus.groovy.grails.web.converters.Converter 接口(查看支持代码,您实际上需要扩展 org.codehaus.groovy.grails.web.converters.AbstractConverter),并且创建相关的支持 classes 来进行转换(这一切都被设计为可扩展的,尽管我认为我没有看到有人这样做)。这会很有趣,而且可能是一次很好的学习经历,但正如我所说 - 考虑到更直接的实施是多么简单,工作量远远超过它的价值。