Grails JSON Marshaller显示与原始日期不同的日期值

时间:2016-05-30 20:26:17

标签: json grails

在我的Grails应用程序中,从数据库中读取的原始日期等于:

{"endDate": "2015-10-19T16:00:00Z"}

虽然JSON结果是:

{{1}}

我认为这可能与时区转换有关。如何在JSON中显示没有任何时区转换的原始日期?

3 个答案:

答案 0 :(得分:5)

根据您所在的时区,2015-10-19 19:00:00.02015-10-19T16:00:00Z可能不会有不同的时间,它们可能只是同一时间的不同表示(即时)。

就我而言,我使用自定义编组器来确保API的JSON响应中的时间始终使用UTC时区。我的定制marshaller看起来像这样:

import org.springframework.stereotype.Component

@Component
class DateMarshaller implements CustomMarshaller {

    @Override
    def getSupportedTypes() {
        Date
    }

    @Override
    Closure getMarshaller() {
        { Date date ->

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

请记住在Config.groovy中注册此marshaller用于Spring bean扫描的软件包。它实现的接口是:

interface CustomMarshaller {

    /**
     * Indicates the type(s) of object that this marshaller supports
     * @return a {@link Class} or collection of {@link Class} 
     * if the marshaller supports multiple types
     */
    def getSupportedTypes()

    Closure getMarshaller()
}

然后我有一个服务,为相关类型注册CustomMarshaller的所有实例:

import grails.converters.JSON
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware

import javax.annotation.PostConstruct

class MarshallerRegistrarService implements ApplicationContextAware {

    static transactional = false

    ApplicationContext applicationContext

    // 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() {

        Map<String, CustomMarshaller> marshallerBeans = applicationContext.getBeansOfType(CustomMarshaller)

        marshallerBeans.values().each { CustomMarshaller customMarshaller ->

            customMarshaller.supportedTypes.each { Class supportedType ->
                JSON.registerObjectMarshaller supportedType, customMarshaller.marshaller
            }
        }
    }
}

这是一个相当复杂的解决方案,但在我的情况下,我使用的是Grails 2.5.X.如果我使用的是Grails 3.X,我会尝试使用JSON视图。

答案 1 :(得分:0)

如果我的内存是正确的,JSON规范实际上并没有定义日期格式的格式。但是每个人都使用ISO 8601,所以它是事实上的标准。大多数人总是使用祖鲁时区。

我前段时间搜索过自己,试图强制Grails JSON在某个时区渲染日期,但失败了。在我的Grails Web应用程序中,我只是将日期字段声明为文本,并将它们格式化为适当的时区并在我自己的代码中进行格式化。从好的方面来说,它还有一个额外的好处,你可以保证它在未来保持这种状态。 (我从大约1.1开始就使用Grails,并且确实在几次看到了重大变化。)

答案 2 :(得分:0)

正在处理使用grails 2.3.11构建的旧应用程序,由于某些未知原因,@Dónal的解决方案无法正常工作。幸运的是,我发现了一种更容易/更直接的方法来在mrhaki's blog上注册自定义编组器。

因此,我制作了一个默认的DateMarshaller副本,该副本驻留在org.codehaus.groovy.grails.web.converters.marshaller.json中,并在我的自定义DateMarshaller中修改了日期格式,然后使用下面的代码段注册了marshaller,摘自mrhaki的帖子。

dateMarshaller(ObjectMarshallerRegisterer) {
    // Assign custom marshaller instance.
    marshaller = new DateMarshaller()

    // Set converter class type.
    converterClass = JSON

    // Optional set priority. Default value is 0.
    priority = 1
}

只需确保“自定义编组器”的优先级比默认优先级高。就像魅力一样!