在Grails REST API项目中,默认情况下Grails会读取属性并呈现属性,假设是驼峰(camelCase)。但是,在许多流行的REST API中,参数名称在snake case(snake_case)上标准化。如何在Grails中最有效地启用此自动转换?
例如,在请求正文中,我想接受蛇案输入。
{
"first_name": "John"
}
在响应机构中,我想发送蛇案例输出。
{
"last_name": "Doe"
}
但我希望在Grails中遵循Groovy约定简化我的域类,使用camel case和Groovy自动生成的getter和setter。
class User {
String firstName
String lastName
}
我想避免更改我的MongoDB架构,其中99%的字段以camelCase命名。但是我确实看到至少in the MongoDB docs,首选的是用snake_case命名MongoDB字段。
答案 0 :(得分:0)
您可以使用https://github.com/google/gson序列化/反序列化您的类,并设置字段命名策略:
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create()
这意味着您应该将您的请求/响应主体作为文本,而不是依赖Grails提供的自动json反序列化。
另一个选项,至少对您的回答而言,是注册自定义JSON编组程序。您可以在bootstrap.groovy中执行此操作。在下面的示例代码中,我实现了一个标记接口,以便可以明确地提名应该序列化为蛇案例的对象。
interface SnakeCase {
}
要作为snake case导出的域对象实现此接口
class Person implements SnakeCase {
String surname
String firstName
String middleNames
String someOtherField
static constraints = {
}
}
然后在bootstrap.groovy中注册了一个自定义JSON编组程序
class BootStrap {
def grailsApplication
def init = { servletContext ->
JSON.registerObjectMarshaller(SnakeCase, { SnakeCase o ->
def result = [:]
if (grailsApplication.isDomainClass(o.class)) {
o.domainClass.persistentProperties.each { GrailsDomainClassProperty p ->
def name = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, p.name)
result[name] = o[p.name]
}
} else {
o.properties.each {
def name = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, it.key as String)
result[name] = it.value
}
}
return result
})
}
def destroy = {
}
}
请注意,grails域类或常规POGO类之间存在区别。您还可以添加黑/白名单机制,以更好地控制哪些属性被序列化。此示例使用Guava CaseFormat实用程序来执行实际的蛇形外壳
这个marshaller注册后,只需在控制器方法中使用JSON格式化程序
def ajaxListPeople() {
def list = Person.list();
render(list as JSON)
}