Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change date/time format to ISO8601 on JSON serialization #548

Merged
merged 7 commits into from
Jul 31, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package br.com.caelum.vraptor.deserialization.gson;

import java.util.Collections;
import java.util.List;

import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.serialization.gson.PackageComparator;

import com.google.common.collect.Lists;
import com.google.gson.JsonDeserializer;

@Component
@SuppressWarnings("rawtypes")
public class DefaultJsonDeserializers implements JsonDeserializers {

private List<JsonDeserializer> deserializers;

public DefaultJsonDeserializers(List<JsonDeserializer> deserializers) {
this.deserializers = Lists.newArrayList(deserializers);

sortDeserializers();
}

public List<JsonDeserializer> getDeserializers() {
return deserializers;
}

/**
* Override this method if you want another ordering strategy.
*/
protected void sortDeserializers() {
Collections.sort(this.deserializers, new PackageComparator());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

Expand Down Expand Up @@ -48,9 +47,9 @@ public class GsonDeserialization implements Deserializer {

private final HttpServletRequest request;

public GsonDeserialization(ParameterNameProvider paramNameProvider, List<JsonDeserializer> adapters, HttpServletRequest request) {
public GsonDeserialization(ParameterNameProvider paramNameProvider, JsonDeserializers adapters, HttpServletRequest request) {
this.paramNameProvider = paramNameProvider;
this.adapters = adapters;
this.adapters = adapters.getDeserializers();
this.request = request;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package br.com.caelum.vraptor.deserialization.gson;

import java.util.List;

import com.google.gson.JsonDeserializer;

public interface JsonDeserializers {

@SuppressWarnings("rawtypes")
List<JsonDeserializer> getDeserializers();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package br.com.caelum.vraptor.serialization.gson;

import java.util.Collections;
import java.util.List;

import br.com.caelum.vraptor.ioc.Component;
Expand All @@ -9,6 +10,7 @@
import com.google.gson.JsonSerializer;

@Component
@SuppressWarnings("rawtypes")
public class DefaultJsonSerializers implements JsonSerializers {

private static boolean isHibernateProxyPresent;
Expand All @@ -22,16 +24,22 @@ public class DefaultJsonSerializers implements JsonSerializers {
}
private List<JsonSerializer> serializers;

@SuppressWarnings("rawtypes")
public DefaultJsonSerializers(List<JsonSerializer> serializers) {
this.serializers = Lists.newArrayList(serializers);
if (isHibernateProxyPresent) {
if (isHibernateProxyPresent)
this.serializers.add(new HibernateProxySerializer());
}

sortSerializers();
}

public List<JsonSerializer> getSerializers() {
return serializers;
}


/**
* Override this method if you want another ordering strategy.
*/
protected void sortSerializers() {
Collections.sort(this.serializers, new PackageComparator());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package br.com.caelum.vraptor.serialization.gson;

import java.util.Comparator;

public final class PackageComparator implements Comparator<Object> {

private static final String CORE_ADAPTER = "br.com.caelum.vraptor.serialization.gson.adapters";
private static final String ISO8601_ADAPTER = "br.com.caelum.vraptor.serialization.iso8601.gson";

public int compare(Object o1, Object o2) {
return giveMorePriorityToISO8601Adapters(o1, o2);
}

private int giveMorePriorityToISO8601Adapters(Object o1, Object o2) {
String packageNameO1 = o1.getClass().getPackage().getName();
String packageNameO2 = o2.getClass().getPackage().getName();

if (packageNameO1.startsWith(CORE_ADAPTER) && packageNameO2.startsWith(ISO8601_ADAPTER))
return -1;

if (packageNameO1.startsWith(ISO8601_ADAPTER) && packageNameO2.startsWith(CORE_ADAPTER))
return 1;

return packageNameO1.compareTo(packageNameO2);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package br.com.caelum.vraptor.serialization.iso8601.gson;

import java.lang.reflect.Type;

import java.text.ParseException;
import java.util.Calendar;

import br.com.caelum.vraptor.converter.ConversionError;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.util.ISO8601Util;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;

@Component
public class CalendarISO8601Deserializer implements JsonDeserializer<Calendar> {

private final ISO8601Util iso8601;

public CalendarISO8601Deserializer(ISO8601Util iso8601) {
this.iso8601 = iso8601;
}

public Calendar deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

try {
String value = json.getAsString();

Calendar calendar = iso8601.toCalendar(value);

return calendar;
} catch (ParseException e) {
throw new ConversionError("Error to convert Calendar: " + e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package br.com.caelum.vraptor.serialization.iso8601.gson;

import java.lang.reflect.Type;
import java.util.Calendar;

import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.util.ISO8601Util;

import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

@Component
public class CalendarISO8601Serializer implements JsonSerializer<Calendar> {

private final ISO8601Util iso8601;

public CalendarISO8601Serializer(ISO8601Util iso8601) {
this.iso8601 = iso8601;
}

public JsonElement serialize(Calendar calendar, Type typeOfSrc, JsonSerializationContext context) {

String json = iso8601.fromCalendar(calendar);

return new JsonPrimitive(json);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package br.com.caelum.vraptor.serialization.iso8601.gson;

import java.lang.reflect.Type;
import java.text.ParseException;
import java.util.Date;

import br.com.caelum.vraptor.converter.ConversionError;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.util.ISO8601Util;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;

@Component
public class DateISO8601Deserializer implements JsonDeserializer<Date> {

private final ISO8601Util iso8601;

public DateISO8601Deserializer(ISO8601Util iso8601) {
this.iso8601 = iso8601;
}

public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

try {
String value = json.getAsString();

Date date = iso8601.toDate(value);

return date;
} catch (ParseException e) {
throw new ConversionError("Error to convert Date: " + e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package br.com.caelum.vraptor.serialization.iso8601.gson;

import java.lang.reflect.Type;
import java.util.Date;

import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.util.ISO8601Util;

import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

@Component
public class DateISO8601Serializer implements JsonSerializer<Date> {

private final ISO8601Util iso8601;

public DateISO8601Serializer(ISO8601Util iso8601) {
this.iso8601 = iso8601;
}

public JsonElement serialize(Date date, Type typeOfSrc, JsonSerializationContext context) {

String json = iso8601.fromDate(date);

return new JsonPrimitive(json);
}
}
104 changes: 104 additions & 0 deletions vraptor-core/src/main/java/br/com/caelum/vraptor/util/ISO8601Util.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@

/***
* Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package br.com.caelum.vraptor.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import br.com.caelum.vraptor.ioc.Component;

/**
* Helper class for handling ISO8601 strings of the following format:
* "1982-06-10T05:00:00.000-03:00". It also supports parsing the "Z" timezone.
*
* @author Rafael Dipold
*/
@Component
public final class ISO8601Util {

/** Default Extended Format */
private static final String DEFAULT_ISO8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";

private static final String REGEX_ISO8601 = "^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)?)?)?$";
// 1 2 3 4 5 6 7 8 9 10 11

private static final SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_ISO8601_FORMAT);

/** Transform Calendar to ISO8601 string. */
public String fromCalendar(final Calendar calendar) {
formatter.setTimeZone(calendar.getTimeZone());
return fromDate(calendar.getTime());
}

/** Transform java.util.Date to ISO8601 string. */
public String fromDate(final Date date) {
String formatted = formatter.format(date);
formatted = formatted.replaceAll("[+-]00:?00$", "Z");
return formatted;
}

/** Get current date and time formatted as ISO8601 string. */
public String now() {
return fromCalendar(GregorianCalendar.getInstance());
}

/** Transform ISO8601 string to Calendar
* @throws ParseException */
public Calendar toCalendar(final String iso8601String) throws ParseException {
Pattern pattern = Pattern.compile(REGEX_ISO8601);
Matcher matcher = pattern.matcher(iso8601String);

if (matcher.matches()) {
int year = matcher.group(1) != null ? Integer.valueOf(matcher.group(1)) : 0;
int month = matcher.group(2) != null ? Integer.valueOf(matcher.group(2)) - 1 : 0;
int day = matcher.group(3) != null ? Integer.valueOf(matcher.group(3)) : 0;

int h = (matcher.group(4) != null ? Integer.valueOf(matcher.group(4)) : 0);
int m = (matcher.group(5) != null ? Integer.valueOf(matcher.group(5)) : 0);
int s = (matcher.group(6) != null ? Integer.valueOf(matcher.group(6)) : 0);
int ms = Math.round(Float.parseFloat("0." + (matcher.group(7) != null ? matcher.group(7) : "0")) * 1000);

TimeZone timeZone = TimeZone.getTimeZone("GMT" + (matcher.group(8) != null ? matcher.group(8) : ""));

Calendar calendar = GregorianCalendar.getInstance(timeZone);
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, h);
calendar.set(Calendar.MINUTE, m);
calendar.set(Calendar.SECOND, s);
calendar.set(Calendar.MILLISECOND, ms);

return calendar;
}
else
throw new java.text.ParseException("Unparseable ISO8601 date format: " + iso8601String, 0);
}

/** Transform ISO8601 string to java.util.Date */
public Date toDate(final String iso8601String) throws ParseException {
Calendar calendar = toCalendar(iso8601String);
return calendar.getTime();
}
}
Loading