【问题标题】:Grails 3 JSON Views custom rendering one-to-many associationsGrails 3 JSON Views 自定义渲染一对多关联
【发布时间】:2018-01-20 23:22:16
【问题描述】:

好的,我已经尝试了我所知道的一切来自定义呈现与 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 要求更改属性输出。

请帮忙:-(

【问题讨论】:

  • 顺便说一句 - 我已经制定了一个临时解决方案,其中仅包括我通过它的 gson 对订户类所需的属性,但这不是预期的效果。我希望在直接向订户进行休息呼叫时能够保留所有属性,但在对有许多订户的票进行休息呼叫时限制属性

标签: json views grails-3.0


【解决方案1】:

如果我理解正确,当您对票证进行 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
    }
}

【讨论】:

    【解决方案2】:

    如果这是您希望此对象在呈现为 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
    

    返回由编组器定义的对象的 JSON 表示

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-05
      • 2011-05-17
      • 2012-03-27
      相关资源
      最近更新 更多