// // Copyright 2010 Cinch Logic Pty Ltd. // // http://www.chililog.com // // 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 org.chililog.server.common; import java.io.Reader; import java.lang.reflect.Field; import org.apache.commons.lang.StringUtils; import org.chililog.server.workbench.HttpRequestHandler; import com.google.gson.FieldNamingStrategy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; /** * <p> * Serializes Java objects into JSON format and deserializes JSON back into Java object(s). * </p> * <p> * Wrapper for GSON (http://code.google.com/p/google-gson/). * </p> * * @author vibul * */ public class JsonTranslator { private static Log4JLogger _logger = Log4JLogger.getLogger(HttpRequestHandler.class); private Gson _gson = null; /** * Returns the singleton instance for this class */ public static JsonTranslator getInstance() { return SingletonHolder.INSTANCE; } /** * SingletonHolder is loaded on the first execution of Singleton.getInstance() or the first access to * SingletonHolder.INSTANCE, not before. * * @see http://en.wikipedia.org/wiki/Singleton_pattern */ private static class SingletonHolder { public static final JsonTranslator INSTANCE = new JsonTranslator(); } /** * <p> * Singleton constructor that creates our reusable GSON object. * </p> * * <p> * If there are any errors, the JVM is terminated. Without valid application properties, we will fall over elsewhere * so might as well terminate here. * </p> */ private JsonTranslator() { try { GsonBuilder builder = new GsonBuilder(); if (AppProperties.getInstance().getJsonPretty()) { builder.setPrettyPrinting(); } builder.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); builder.setFieldNamingStrategy(new ChiliLogFieldNamingStrategy()); builder.disableHtmlEscaping(); _gson = builder.create(); } catch (Exception e) { _logger.error("Error initializing JSON translator: " + e.getMessage(), e); System.exit(1); } } /** * Serialize a Java object to a String * * @param o * Object to serialize * @return String serialization of the java object in JSON format. */ public String toJson(Object o) { return _gson.toJson(o); } /** * Serialize a Java object into the specified appender. * * @param o * Object to serialize * @param appender * Appender into which the JSON form of the object will be written */ public void toJson(Object o, Appendable appender) { _gson.toJson(o, appender); } /** * Deserializes a JSON string into a Java object of the specified class. * * @param <T> * the type of the desired object * @param json * the string from which the object is to be deserialized * @param classOfT * the class of T * @return an object of type T from the string. null if json is null or empty string. */ public <T> T fromJson(String json, Class<T> classOfT) { if (StringUtils.isBlank(json)) { return null; } // Have to trim because of bug with trailing white space // http://groups.google.com/group/google-gson/browse_thread/thread/6f12cf80b12a85b8 return _gson.fromJson(json.trim(), classOfT); } /** * Deserializes a JSON stream into a Java object of the specified class. * * @param <T> * the type of the desired object * @param json * the reader containing the JSON string from which the object is to be deserialized * @param classOfT * the class of T * @return an object of type T from the reader */ public <T> T fromJson(Reader json, Class<T> classOfT) { return _gson.fromJson(json, classOfT); } /** * This class tells gson to convert <code>_myFieldName</code> to <code>MyFieldName</code> * * @author vibul * */ public static class ChiliLogFieldNamingStrategy implements FieldNamingStrategy { @Override public String translateName(Field field) { StringBuilder sb = new StringBuilder(field.getName()); sb.replace(0, 2, sb.substring(1, 2).toUpperCase()); return sb.toString(); } } }