使用自定义转换器时,在Grails中处理PUT / POST请求

时间:2015-06-19 14:35:48

标签: json rest grails

我正在编写Grail REST服务,并且我已经定义了自定义JSON转换器。例如,我有一个event类,只要客户端请求这样的对象,就会这样转换...

// in src/groovy/EventMarshaller.groovy
class EventMarshaller {

void register(Object config) {
    config.registerObjectMarshaller(Event) { Event e ->
        return [
            id: e.id,
            title: e.title,
            description: e.description,
            dateCreated: e.dateCreated.format('yyyy-MM-dd'),
            creator: e.creator
        ]
    }
}

我在EventMarshaller中注册CustomObjectMarshaller,其中需要named config参数,以便可以容纳不同的REST API版本...

// in src/groovy/CustomObjectMarshallers.groovy
def register(String str) {
    JSON.createNamedConfig(str) { cfg ->
        marshallers.each {
            it.register(cfg);
        }
    }
}

// in BootStrap.groovy init section...
def springContext = WebApplicationContextUtils.getWebApplicationContext( servletContext );
    springContext.getBean("customObjectMarshallers").register("v1");

每当我通过REST API调用GET event对象时,这就像一个魅力,域对象被转换为指定的JSON格式。例如,我的event控制器有一个index操作...

def index(String v) 
{
    def configName = 'v' + (v ?: 1)

    def listOfEvents = Event.list()

    // why does this only work when converting domain object to json?
    JSON.use(configName) {                  
        respond listOfEvents
    }
}

现在,当从客户端收到updatesave命令时,我需要PUTPOST个操作。到目前为止,我在update行动中有以下内容......

def update(Long id, String v) 
{
    def configName = 'v' + (v ?: 1)

    // how do I specify the version? JSON.use(configName) doesn't seem to work?
    def jsonobj = JSON.parse(request);
    def newEvent = new Event(jsonobj);
    def evRequest = new EventRequest(jsonobj)       

    evRequest.errors.allErrors.each {
        println it
    }
    ...

任何人都可以解释在将JSON转换为域对象时如何告诉update action使用哪个配置? (我根本没有看到任何在线示例。)此外,解析JSON后,dateCreated对象中的newEvent字段为空。如果存在dateCreated字段,它将被解析为原始date对象,我该如何确保?

这是代码中引用的命令对象......

/**------------------------------------------------------------
// EVENT REQUEST COMMAND OBJECT 
//----------------------------------------------------------**/
class EventRequest
{
    String id;
    String title;
    String description;
    byte[] photo;
    @BindingFormat('yyyy-MM-dd')
    Date dateCreated;

    //------------------------------------------------------------ 
    // IMPORT CONTRAINTS FROM EVENT DOMAIN MODEL
    //------------------------------------------------------------
    static constraints = {
        importFrom Event;
    }
}

它映射到的event域类...

import java.util.Date;
import org.emvigr.user.*
import org.grails.databinding.BindingFormat;

class Event {

    String title
    String description
    byte[] photo
    @BindingFormat('yyyy-MM-dd')
    Date dateCreated

    // we can call user.addToEvents
    static belongsTo = [ 
        creator : User 
    ]

    static hasMany = [
        portals : Portal
    ]

    static constraints = {
        title maxSize: 50
        description nullable: true, maxSize: 300
        photo nullable: true, maxSize: 2 * 1024 * 1024
        dateCreated nullable: true
        portals nullable: true
    }

    // when Events are accessed sort by the dateCreated (descending)
    static mapping = {
        sort dateCreated:"desc"
    }

}

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

感谢Joshua Moore提供有关命名空间和dmahapatro重新绑定日期的信息。我在update中解析日期参数时也遇到了问题,我现在意识到这是因为我(错误)使用命令对象的方式。

对于遇到相同问题的任何人来说,这可能是2.4.4的特殊情况,但根据{{一个类被用作动作的参数时,它只被视为命令对象{3}}。一旦我像这样修改了更新动作......

def update(EventRequestCommand cmd) 
{               
    cmd.errors.allErrors.each {
        println it
    }

    if (!cmd.hasErrors()) {
        def ev = Event.get(cmd.id);
        // save changes
    }
    else {
        // handle error
    }
}

可以以某种方式解析日期。我仍然不知道为什么如果你在我上面的原始代码中创建一个EventRequest类并且我也看到official docs,其中命令对象不是参数,它不起作用。我认为日期仍然可以被解析,但我想这是Grails的另一个令人困惑的方面。