Grails 3 JSON 查看自定义呈现一对多关联

Grails 3 JSON Views custom rendering one-to-many associations

好吧,我已经尝试了我所知道的一切来自定义呈现与 JSON 视图的一对多关联,但惨败。

这是我的票务域的一部分(这里一切都很好)...

class TttTicket {

    String title
    String number
    String description
    TttUser assignee
    String priority
    String status
    TttUser creator


    Date dateCreated
    Date lastUpdated

    static mappedBy = [subscribers : 'none', creator:'none']

    static belongsTo = [project:TttProject, creator:TttUser]
    static hasMany = [subscribers: TttUser]

... blar blar 
}

这是我关联的 gson 渲染模板...

import ttt_api_server.TttTicket

model {
    TttTicket tttTicket
}

json g.render(tttTicket, [excludes:['creator','subscribers','project']]){
    creator {
        id tttTicket.creator.id
        name tttTicket.creator.name
        email tttTicket.creator.email
    }

    project{
        id tttTicket.project.id
        name tttTicket.project.name
    }
}

... 目前运行良好。我现在想限制每个订阅者的属性输出。

如何旋转这些?例如...

import ttt_api_server.TttTicket

model {
    TttTicket tttTicket
}

json g.render(tttTicket, [excludes:['creator','subscribers','project']]){
    creator {
        id tttTicket.creator.id
        name tttTicket.creator.name
        email tttTicket.creator.email
    }
    subscibers g.render(){
        tttTicket.subscribers.each {sub ->
            return {
                name sub.name
            }
        }
    }
    project{
        id tttTicket.project.id
        name tttTicket.project.name
    }
}

这似乎没有在任何地方记录。我想控制此级别每个订阅者的 JSON 输出。不在域级别,因为我可能需要根据我的 JSON 要求更改 属性 输出。

请帮忙:-(

如果我理解正确,当您对票证进行 REST 调用时,您希望 hasMany 关系内的域对象显示指定的属性(在本例中为订阅者)。但是当您直接调用订阅者时,您需要所有属性。

您可以先创建地图,然后根据创建的地图渲染对象(查看this)。 你的情况:

import ttt_api_server.TttTicket

model {
    TttTicket tttTicket
}

json g.render(tttTicket, [excludes:['creator','subscribers','project']]){
    creator {
        id tttTicket.creator.id
        name tttTicket.creator.name
        email tttTicket.creator.email
    }

    def s = tttTicket.subsribers.collect {
        [
            id: it.id,
            name: it.name
        ]
    }

    subscribers s //this part is doing the rendering

    project{
        id tttTicket.project.id
        name tttTicket.project.name
    }
}

如果这是您希望此对象在呈现为 JSON 时呈现的方式,我建议实施 ObjectMarshaller<JSON>:

class TttTicketMarshaller implements ObjectMarshaller<JSON> {

  @Override
  boolean supports(Object object) {
    return object instanceof TttTicket
  }

  @Override
  void marshalObject(Object object, JSON converter) throws ConverterException {
    TttTicket ticket = (TttTicket)object

    def jsonWriter = converter.writer
    jsonWriter.object()
    jsonWriter.key("title")
    jsonWriter.value(ticket.title)

    //other fields

    jsonWriter.key("creator")
    jsonWriter.object()
    jsonWriter.key("id")
    jsonWriter.value(ticket.creator.id)

    //other creator fields
    jsonWriter.endObject()
  }
}

我不是 100% 确定 object()endObject() 功能,但这似乎是正确的用法。

一旦你有了这个,在你的 BootStrap.groovy 中注册它:

def init = { servletContext ->
  JSON.registerObjectMarshaller(new TttTicketMarshaller())
}

有了这一切,您可以简单地使用

render myTicket as JSON

到 return 由编组器定义的 JSON 对象表示