【问题标题】:How does Grails 2.5.6 parse and map request JSON to POGO?Grails 2.5.6 如何解析请求 JSON 并将其映射到 POGO?
【发布时间】:2018-10-25 11:53:34
【问题描述】:

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 的实例。让我们假设默认设置器不起作用;例如,我们不止一次使用的模式是这样的枚举:

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

    int id
    String jsonName

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

这里,customMap 将接受一个整数或字符串,并返回匹配的大小写(或 null,如果不匹配)。

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

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

【问题讨论】:

  • 我在上面提供的链接适用于 Grails 3。在 Grails 2.5.6 中,创建实例的过程完全相同,但发生在 github.com/grails/grails-core/blob/…。 (不同的类,相同的行为)
  • 仅供参考...您不必在测试中使用controller.request.contentType = "application/json",因为您正在执行controller.request.json = validData,这将为您设置内容类型。这发生在github.com/grails/grails-core/blob/v2.5.6/grails-test/src/main/…
  • @JeffScottBrown 不幸的是,bindData 并没有真正记录在案,甚至很难为它编写单元测试。对DataBindingUtils.bindObjectToInstance 进行测试似乎是谨慎的做法,这显然是调用的助手。
  • @JeffScottBrown 恐怕我给人的印象是过于刻薄和不感恩。虽然我经常对 Grails 感到沮丧,但这不应该影响我在这里的交互。所以,对不起,如果我冒犯了。我曾经并且非常感谢您为帮助我而付出的努力! (最后,问题是我没有阅读正确的文档,所以我想我们在那里聊了一会儿。)

标签: json parsing grails pogo


【解决方案1】:

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

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

另见the MWE repo

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

【讨论】:

    猜你喜欢
    • 2022-11-23
    • 2020-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多