注册自定义JSON marshallers

时间:2015-05-29 10:23:17

标签: json rest grails

在我的Grails 2.5.0应用程序中,我使用了一堆自定义JSON marshallers来严格控制我的REST端点返回的JSON格式。目前我在这样的服务中注册这些marshallers

class MarshallerRegistrarService {

    static transactional = false

    LinkGenerator grailsLinkGenerator

    // a combination of eager bean initialization and @PostConstruct 
    // ensures that the marshallers are registered when the app (or 
    // a test thereof) starts
    boolean lazyInit = false

    @PostConstruct
    void registerMarshallers() {

        // a collection of Enums that can be rendered to JSON
        def jsonEnums = [PaymentFrequency, Operation]

        jsonEnums.each { Class enumType ->
            JSON.registerObjectMarshaller(enumType) { Enum enumValue ->
                enumValue.toString()
            }
        }

        JSON.registerObjectMarshaller(TimelineItem) { TimelineItem timelineItem ->
            def domainInstance = timelineItem.item

            return [
                    date: timelineItem.date,
                    type: domainInstance.class.simpleName,
                    item: [id: domainInstance.id],
                    link: grailsLinkGenerator.link(absolute: true, mapping: 'downloadForm', params: [apiVersion: 'v1', id: domainInstance.id])
            ]    
        }

        JSON.registerObjectMarshaller(Date) {

            TimeZone tz = TimeZone.getTimeZone('UTC')
            def formatted = it?.format("yyyy-MM-dd'T'HH:mm:ss'Z'", tz)
            return formatted
        }

        // more marshallers registered here (much more!)
    }
}

这种方法的原因之一是我可以在渲染JSON时访问spring bean(例如grailsLinkGenerator)。

然而,有几个缺点:

  • 在方法体内定义和注册marshallers使得它们难以测试
  • registerMarshallers方法随着编组人数的增加而迅速失控

我更喜欢在其自己的类中定义每个编组器并在resources.groovy中将其注册为Spring bean,这可能吗?

1 个答案:

答案 0 :(得分:1)

当然可以这样做:-) 制作所有marshallers @Component并在实例化期间或之后使用JSON注册它们。另一种方法是使它们@Component并用接口或基类标记它们并在bootstrap / plugin init中注册它们,如下所示:

ctx.getBeansOfType(MarshallerBase).each { name, bean ->
   bean.registerMarshallers()
}

假设每个编组器实现registerMarshallers()方法。 但是还有更多的方法。