12

问题:有没有办法用 request.JSON 数据自动绑定命令对象?

鉴于我的 grails 控制器中的这个简单的 Command 对象:

class ProfileCommand{

int id
String companyName

static constraints = {
    companyName blank: false
    id nullable: false
}

@Override
public String toString() {
    return "ProfileCommand{id=$id, companyName='$companyName'}";
}
}

和我的控制器方法签名:

def update(ProfileCommand command) {...}

如何将request.JSON数据放入我的命令对象?

到目前为止,我能够做到的唯一方法是在update()方法中手动创建命令对象,将 request.JSON 作为构造函数参数传入:

    def command = new ProfileCommand(request.JSON)

    log.debug "Command object contents: $command"

上面的调试命令产生:

Command object contents: ProfileCommand{id=1, companyName='Blub Muckers'}

这正是我想要的(为上述解决方案向 Oliver Tynes 大喊大叫)。不幸的是,在我创建命令后调用command.validate()会产生以下异常:

Class org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException
Message Tag [validate] is missing required attribute [form]

我正在使用 v2.0.3,uris 产生了与 v2.0.4 相同的异常。

在 grails 邮件列表上更新 Per Ian Roberts,您需要将@Validateable注释添加到命令类才能开始validate()工作。谢谢,伊恩!

4

3 回答 3

7

我不确定是否有任何配置方式可以进行自动 JSON 参数数据绑定;您可能能够做的一件事是为您的操作编写一个过滤器,该过滤器接受 JSON 请求输入,基本上将 request.JSON 直接重新映射到根参数映射,理论上这应该允许自动数据绑定发生。

就像是:

class JSONParamMapFilters {
  def filters = {
     before = {
        remapFilter(controller:'yourController', action:'update') {
           request.JSON.each { k,v ->
               params[k] = v
           }
        }
     }
  }
}

然后,您可以通过正则表达式/命名约定将此过滤器扩展到任何适用的控制器操作。

于 2012-05-31T13:50:47.970 回答
4

你应该parseRequest=trueUrlMappings.groovy. 例如:

"/user/$id/$action?"(controller: "userProfile", parseRequest: true) {
    constraints {
        id matches: /^[0-9]+$/
    }
}

然后您可以params在方法参数中使用变量或将 json 绑定到命令对象:

def index(MyCommand command){...}

两者都应该工作。但在某些情况下,它会从 json 中丢失一些信息(绑定到地图)。

于 2013-01-28T08:22:44.643 回答
1

如果您不使用命令对象作为任何控制器操作的参数,那么 Grails 将不会使用 validate 方法自动增强它。您需要使用 @Validateable 注释该类以告诉 Grails 它应该被增强。

http://grails.org/doc/latest/guide/validation.html#validationNonDomainAndCommandObjectClasses

于 2012-05-31T15:22:38.810 回答