Grails 2.5.6 如何解析请求 JSON 并将其映射到 POGO?

How does Grails 2.5.6 parse and map request JSON to POGO?

Tl;dr:我想在 this code 绿色中进行测试 MyCmdTest."data bind works"
感谢 Jeff Scott Brown getting me that far.


我有一个 POGO,其中包含来自 JSON 的一些自定义转换,我希望在 Grails 控制器中收到这些转换:

def myAction(MyCmd myData) {
    ...
}

有:

@Validateable
class MyCmd {
    SomeType some

    void setSome(Object value) {
        this.some = customMap(value)
    }
}

请注意 customMap 如何从 JSON 值(例如字符串)创建 SomeType 的实例。让我们假设默认值 setter 不起作用;例如,我们不止一次遇到的模式是这样的枚举:

enum SomeType {
    Foo(17, "foos"),
    Bar(19, "barista")

    int id
    String jsonName

    SomeType(id, jsonName) {
        this.id = id
        this.jsonName = jsonName
    }
}

此处,customMap 将采用整数或字符串,return 匹配大小写(或 null,如果 none 适合)。

现在,我有一个如下形式的单元测试:

class RegistrationCmdTest extends Specification {
    String validData // hard-coded, conforms to JSON schema

    void test() {
        MyCmd cmd = new MyCmd(JSON.parse(validData))
        // check members: success

        MyCmd cmd2 = JSON.parse(validData) as MyCmd
        // check members: success
    }
}

显然,setSome 在两种变体中都被调用。

我还有一个控制器单元测试,将请求 JSON 设置为相同的字符串:

void "register successfully"() {
    given:
    ResonseCmd = someMock()

    when:
    controller.request.method = 'POST'
    controller.request.contentType = "application/json"
    controller.request.json = validData
    controller.myAction()

    then:
    noExceptionThrown()
    // successful validations: service called, etc.
}

基本上同样的事情也作为集成测试运行。

但是,当 运行 完整应用时,映射 失败 some == null

我必须实现或重写哪些方法,以便 Grails 调用我的转换(此处为 customMap),而不是在它不知道要做什么的地方插入 null

可以使用 @BindUsing 注释自定义数据绑定:

@BindUsing({ newCmd, jsonMap ->
    customMap(jsonMap['someType'])
})
SomeType someType

另见 the MWE repo

来源:Hubert Klein Ikkink @ DZone, Official Docs(还有其他自定义方式)