Grails Java 8 Time JSON Simplification



我正在Grails 3.2.3中设计一个简单的宁静预订系统,并希望使用新的Java 8时间库。

@Resource(uri='/reservation', formats=['json'])
class Reservation {
    String groupName
    int groupSize
    LocalDateTime dateTime
    int durationMinutes
    static belongsTo = [calendar:ReservationCalendar]
    static constraints = {
        calendar        blank:false, nullable:false
        groupName       blank:false, size:2..30
        groupSize       blank:false, min:1
        durationMinutes blank:false, min:1
        dateTime        validator: {
                            if (it.isAfter(LocalDateTime.now().plusMinutes(30L))) {
                                return true
                            } else {
                                return ['dateBeforeEarliestReservationTime']
                            }
                        }
    }
}

我在BootStrap.groovy中插入了以下记录:

def init = { servletContext ->
    new ReservationCalendar(reservationObject:"reservable item1", reservationUnitsPerSlot:5).save()
    new Reservation(calendar:1, groupName:"testers1", groupSize:2, dateTime:LocalDateTime.now().plusHours(2L),  durationMinutes:30).save()
    LocalDateTime maxDaysInFuture;

}

现在,当我运行应用程序时,一切正常。GET/reservation URI 调用 index() 操作并返回:

[{"id":1,"calendar":{"id":1},"dateTime":{"class":"java.time.LocalDateTime","dayOfMonth":23,"dayOfWeek":{"enumType":"java.time.DayOfWeek","name":"MONDAY"},"dayOfYear":23,"hour":18,"minute":18,"month":{"enumType":"java.time.Month","name":"JANUARY"},"monthValue":1,"nano":629000000,"second":46,"year":2017,"chronology":{"calendarType":"iso8601","class":"java.time.chrono.IsoChronology","id":"ISO"}},"durationMinutes":30,"groupName":"testers1","groupSize":2}]

但是当我从某个与 java 无关的客户端去 POST 一个新的保留记录时,我宁愿有某种方式不必了解底层数据结构并有一些干净的输入,例如日期字符串:

[{"id":1,"calendar":{"id":1},"dateTime":"01-23-2017 6:30PM CST","durationMinutes":30,"groupName":"testers1","groupSize":2}]

我一直在阅读Grails文档,但没有任何关于如何自定义资源输入/输出的明确示例。我想要一组字段,例如:

"dateTime":{"dayOfMonth":23,"month":1,"year":2017,"hour":18,"minute":30},

并从这些字段创建时间对象。

我的解决方法如下:

1) 我在域类中使用常规 Date 对象作为 dateTime。我仍然在使用 Java 8 time api——当我对 Date 进行验证和逻辑时,我每次都将其转换为 LocalDateTime。

LocalDateTime t = LocalDateTime.ofInstant(dateTime.toInstant(), ZoneId.systemDefault());

2)在BootStrap.groovy中,我已经在我的JSON编组器中注册了一种友好的输出格式。

SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy HH:mm"); 
JSON.registerObjectMarshaller(Reservation) {
    def returnArray = [:]
    returnArray['groupName'] = it.groupName
    returnArray['groupSize'] = it.groupSize
    returnArray['dateTime'] = dateFormat.format(it.dateTime) // other piece of this is in application.yml (grails.databinding.dateFormats)
    return returnArray
}

3)在application.yml中,我定义了grails.databinding.dateFormats以包含相同的友好格式:

grails:
    databinding:
        dateFormats:
            -  "MM-dd-yyyy HH:mm"

结果是一个 JSON,其输出如下所示:

[{"groupName":"testers1","groupSize":2,"dateTime":"01-24-2017 20:47"}]

执行 POST 以添加记录,我只需要提供日期时间作为格式化字符串。

"dateTime":"01-24-2017 21:47"

如果您知道一个更时髦的解决方案,请随时发布!

最新更新