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(还有其他自定义方式)
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(还有其他自定义方式)