Подтвердить что ты не робот

Командный объект 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(). Спасибо, Ян!

4b9b3361

Ответ 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