在Grails REST API中自动将蛇案例转换为驼峰案例?

时间:2016-07-04 18:09:27

标签: mongodb rest grails

在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字段。

1 个答案:

答案 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)
}