Командный объект Grails: как загрузить request.JSON в него?
Вопрос: существует ли способ автоматического связывания объекта команды с данными request.JSON?
Учитывая этот простой объект Command в моем контроллере grails:
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'}
Это именно то, что я хочу (большой крик для Оливера Тайнса для вышеупомянутого решения). К сожалению, вызов command.validate()
после создания команды вызывает следующее исключение:
Class org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException
Message Tag [validate] is missing required attribute [form]
Я использую v2.0.3, урис создал то же исключение w/v2.0.4.
UPDATE
Для Иана Робертса в списке рассылки Grails вам нужно добавить аннотацию @Validateable
к классу команд, чтобы получить работу validate()
. Спасибо, Ян!
Ответы
Ответ 1
Я не уверен, есть ли что-то конфигурируемое для автоматической привязки данных параметров JSON; одна вещь, которую вы могли бы сделать, это написать фильтр для ваших действий, которые принимают входной запрос JSON, который в основном перенаправляет request.JSON непосредственно на карту корневых params, что теоретически позволяет автоматическое связывание данных.
что-то вроде:
class JSONParamMapFilters {
def filters = {
before = {
remapFilter(controller:'yourController', action:'update') {
request.JSON.each { k,v ->
params[k] = v
}
}
}
}
}
Затем вы можете расширить этот фильтр с помощью соглашений о регулярном выражении/именовании с любыми применимыми действиями контроллера.
Ответ 2
Вы должны использовать parseRequest=true
в UrlMappings.groovy
. Например:.
"/user/$id/$action?"(controller: "userProfile", parseRequest: true) {
constraints {
id matches: /^[0-9]+$/
}
}
Затем вы можете использовать переменную params
или связать json с объектом команды в аргументах метода:
def index(MyCommand command){...}
Оба должны работать. Но в некоторых случаях он теряет некоторую информацию от json (привязка к картам).
Ответ 3
Если вы не используете командный объект в качестве параметра для любых действий контроллера, Grails не будет автоматически его активировать с помощью метода проверки. Вам необходимо аннотировать класс с помощью @Validateable, чтобы сообщить Grails, что он должен быть расширен.
http://grails.org/doc/latest/guide/validation.html#validationNonDomainAndCommandObjectClasses