package com.breeze.util;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.internal.LinkedTreeMap;
public class JsonGson {
/**
* Convert the object tree to JSON, including the $id. $ref and $type
* properties
*
* @param obj The obj to serialize to json
* @return The json string.
*/
public static String toJson(Object obj) {
return toJson(obj, false, false);
}
/**
* Convert the object tree to JSON
*
* @param obj The root object to be serialized to json.
* @param includesBreezeEntities
* Whether to add the $id and $ref and $type properties when serializing the object.
* @param isHibernate
* Whether to add Hibernate proxy handling when serializing the object.
* @return A json string.
*/
public static String toJson(Object obj, boolean includesBreezeEntities, boolean isHibernate) {
try {
GsonBuilder gsonBuilder = newGsonBuilder(includesBreezeEntities, isHibernate);
Gson gson = gsonBuilder.create();
return gson.toJson(obj);
} catch (Exception e) {
throw new RuntimeException("Exception serializing json: " + obj, e);
}
}
/**
* Convert the JSON string to a Map of Lists of Maps...
*
* @param source A json string
* @return A Map representing the deserialized json.
*/
public static Map fromJson(String source) {
try {
Gson gson = newGsonBuilder().create();
LinkedTreeMap result = gson.fromJson(source, LinkedTreeMap.class);
return result;
} catch (Exception e) {
throw new RuntimeException("Exception deserializing json: "
+ source, e);
}
}
/**
*
* Convert a JSON string containing a json Array into an Array of Maps
*
* @param source A string containing a json array i.e. "[....]".
* @return An array of Maps.
*/
public static Map[] fromJsonArray(String source) {
try {
Gson gson = newGsonBuilder().create();
LinkedTreeMap[] result = gson.fromJson(source, LinkedTreeMap[].class);
return result;
} catch (Exception e) {
throw new RuntimeException("Exception deserializing " + source, e);
}
}
/**
* Convert the Map into an instance of the given class
*
* @param clazz The class to deserialize into.
* @param map The data to deserialize.
* @return An instance of the specified class.
*/
public static Object fromMap(Class<?> clazz, Map map) {
String json = toJson(map);
return fromJson(clazz, json);
}
/**
* Convert a json string ito an instance of the specified class.
* @param clazz The class to deserialize into.
* @param json The data to deserialize.
* @return An instance of the specified class.
*/
public static Object fromJson(Class<?> clazz, String json) {
try {
Gson gson = newGsonBuilder().create();
Object result = gson.fromJson(json, clazz);
return result;
} catch (Exception e) {
throw new RuntimeException("Unable to populate " + clazz.getName()
+ " from " + json, e);
}
}
/** @return newGsonBuilder(false, false) */
public static GsonBuilder newGsonBuilder() {
return newGsonBuilder(false, false);
}
/**
* @param useBreezeTypeAdapter
* Whether to add the $id and $ref and $type properties when serializing the object.
* @param useHibernateProxyAdapter
* Whether to add Hibernate proxy handling when serializing the object.
* @return a GsonBuilder with a DateTypeAdapter
*/
public static GsonBuilder newGsonBuilder(boolean useBreezeTypeAdapter, boolean useHibernateProxyAdapter) {
// setDateFormat in commented out line below works fine for
// deserialization but doesn't handle
// serialization properly because of need for a TimeZone setting.
// Hence the need for the DateTypeAdapter below.
// return new GsonBuilder().setDateFormat(ISO8601_DATEFORMAT);
GsonBuilder gsonBuilder = new GsonBuilder()
.registerTypeAdapter(Date.class, new DateTypeAdapter());
if (useBreezeTypeAdapter) {
gsonBuilder = gsonBuilder
.registerTypeAdapterFactory(new BreezeTypeAdapterFactory());
}
if (useHibernateProxyAdapter) {
gsonBuilder = gsonBuilder
.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY)
.registerTypeAdapterFactory(HibernateCollectionTypeAdapter.FACTORY);
}
return gsonBuilder;
}
// Ugh....
// private static final String ISO8601_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss";
// private static final String ISO8601_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
// private static final String ISO8601_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX";
// private static final String ISO8601_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";
// private static final String ISO8601_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ssX";
private static final String ISO8601_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
private static class DateTypeAdapter implements
JsonSerializer<Date>,
JsonDeserializer<Date> {
private final DateFormat _dateFormat;
private DateTypeAdapter() {
_dateFormat = new SimpleDateFormat(ISO8601_DATEFORMAT, Locale.US);
_dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
@Override
public synchronized JsonElement serialize(Date date, Type type,
JsonSerializationContext jsonSerializationContext) {
return new JsonPrimitive(_dateFormat.format(date));
}
@Override
public synchronized Date deserialize(JsonElement jsonElement,
Type type, JsonDeserializationContext jsonDeserializationContext) {
try {
return _dateFormat.parse(jsonElement.getAsString());
} catch (ParseException e) {
throw new JsonParseException(e);
}
}
}
}