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

Grails JSON Marshaller显示的日期值与原始日期不同,json,grails,Json,Grails,在my Grails应用程序中,从数据库读取的原始日期等于: { endDate=2015-10-19 19:00:00.0} 而JSON结果是: {"endDate": "2015-10-19T16:00:00Z"} 我认为这可能与时区转换有关。如何在JSON中显示原始日期而不进行任何时区转换?如果我的内存正确,JSON规范实际上没有为日期格式定义格式。但每个人都使用ISO8601,所以它有点像事实上的标准。而且大多数人总是使用祖鲁时区 一段时间前,我搜索了自己,寻找强制GrailsJSO

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

{ endDate=2015-10-19 19:00:00.0}
而JSON结果是:

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

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

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


一段时间前,我搜索了自己,寻找强制GrailsJSON呈现特定时区的日期的方法,但失败了。在我的GrailsWeb应用程序中,我只是将日期字段声明为文本,并在我自己的代码中将其格式化为适当的时区和格式。从好的方面来说,它还有一个额外的好处,你可以保证它在未来保持这种状态。(我从大约1.1开始就在使用Grails,并在一些场合看到了突破性的变化。)

如果我的记忆是正确的,JSON规范实际上并没有为日期格式定义格式。但每个人都使用ISO8601,所以它有点像事实上的标准。而且大多数人总是使用祖鲁时区


一段时间前,我搜索了自己,寻找强制GrailsJSON呈现特定时区的日期的方法,但失败了。在我的GrailsWeb应用程序中,我只是将日期字段声明为文本,并在我自己的代码中将其格式化为适当的时区和格式。从好的方面来说,它还有一个额外的好处,你可以保证它在未来保持这种状态。(我从大约1.1开始使用Grails,并且在一些情况下确实看到了突破性的变化。)

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

在我的例子中,我使用自定义封送器来确保API的JSON响应中的时间始终使用UTC时区。我的自定义封送员如下所示:

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
中注册此封送拆收器用于Springbean扫描的包。它实现的接口是:

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
导入org.springframework.context.ApplicationContext
导入org.springframework.context.ApplicationContextAware
导入javax.annotation.PostConstruct
类MarshallerRegistrarService实现ApplicationContextAware{
静态事务=false
应用上下文应用上下文
//eager bean初始化和@PostConstruct的组合确保了在
//应用程序(或其测试)启动
布尔lazyInit=false
@施工后
无效注册人(){
Map marshallerBeans=applicationContext.getBeansOfType(CustomMarshaller)
values()。每个{CustomMarshaller CustomMarshaller->
customMarshaller.supportedTypes.each{Class supportedType->
JSON.registerObjectMarshaller支持的类型,customMarshaller.marshaller
}
}
}
}

这是一个相当复杂的解决方案,但在我的例子中,我使用的是Grails2.5.X。如果我使用的是Grails 3.X,我会尝试使用JSON视图。

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

在我的例子中,我使用自定义封送器来确保API的JSON响应中的时间始终使用UTC时区。我的自定义封送员如下所示:

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
中注册此封送拆收器用于Springbean扫描的包。它实现的接口是:

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
导入org.springframework.context.ApplicationContext
导入org.springframework.context.ApplicationContextAware
导入javax.annotation.PostConstruct
类MarshallerRegistrarService实现ApplicationContextAware{
静态事务=false
应用上下文应用上下文
//eager bean初始化和@PostConstruct的组合确保了在
//应用程序(或其测试)启动
布尔lazyInit=false
@施工后
无效注册人(){
Map marshallerBeans=applicationContext.getBeansOfType(CustomMarshaller)
values()。每个{CustomMarshaller CustomMarshaller->
customMarshaller.supportedTypes.each{Class supportedType->
JSON.registerObjectMarshaller支持的类型,customMarshaller.marshaller
}
}
}
}

这是一个相当复杂的解决方案,但在我的例子中,我使用的是Grails2.5.X。如果我使用的是Grails 3.X,我会尝试改用JSON视图。

处理一个使用Grails 2.3.11构建的旧应用程序,其中@dónal的解决方案由于一些未知的原因无法工作。幸运的是,我找到了一种更简单/更直接的方法来在上注册自定义封送拆收器

因此,我复制了org.codehaus.groovy.grails.web.converters.marshaller.json中的默认DateMarshaller,并在自定义DateMarshaller中修改了日期格式化程序,然后使用下面摘自mrhaki文章的代码段注册了marshaller

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

    // Set converter class type.
    converterClass = JSON

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

只需确保自定义封送拆收器的优先级高于默认封送拆收器。工作起来很有魅力

处理一个使用grails 2.3.11构建的旧应用程序,其中@Dónal的解决方案由于某种未知的原因无法工作。幸运的是,我找到了一种更简单/更直接的方法来在上注册自定义封送拆收器

因此,我复制了一个默认DateMarshaller,它位于org.codehaus.groovy.grails.web.converters.marsha中