Java tutorial
/* * Copyright 2013-2014 the original author or authors. * * 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.thiaguten.contrib; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonNull; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; /** * This class helps with some more features for converting and manipulating JSON using GSON API. * * @author Thiago Gutenberg C. da Costa * @author Leandro Ozelame M. Ferreira * @since 1.0.0 */ public abstract class JsonContrib { private static final Gson GSON_INSTANCE; private static final AtomicInteger COUNTER; static { GSON_INSTANCE = new GsonBuilder().serializeNulls().setDateFormat("yyyy-MM-dd").create(); COUNTER = new AtomicInteger(0); } public static Gson getGsonInstance() { return GSON_INSTANCE; } /** * @param object the specified object to be serialized * @return Json representation of {@code object} * @see com.google.gson.Gson#toJson(Object) */ public static String objectToJson(Object object) { return getGsonInstance().toJson(object); } /** * @param json the string from which the object is to be deserialized * @param classOfT the class of T * @param <T> the type of the desired object * @return an object of type T from the string * @see com.google.gson.Gson#fromJson(String, Class) */ public static <T> T jsonToObject(String json, Class<T> classOfT) { return getGsonInstance().fromJson(json, classOfT); } /** * @param object the object for which Json representation is to be created setting for Gson * @return Json representation of {@code object} * @see com.google.gson.Gson#toJsonTree(Object) */ public static JsonElement objectToJsonElementTree(Object object) { return getGsonInstance().toJsonTree(object); } /** * Parses the object into its equivalent JsonElement representation. * <p/> * Will be thrown {@code JsonSyntaxException} if the specified object is an instance of String and * * @param object the specified object to be parsed * @return JsonElement representation of specified object * //@throws JsonSyntaxException */ public static JsonElement parseObject(Object object) /*throws JsonSyntaxException*/ { if (object != null && object instanceof String) { try { return new JsonParser().parse((String) object); } catch (JsonSyntaxException e) { return null; } } else { return objectToJsonElementTree(object); } } /** * Checks if a string is a valid representation of a JSON * * @param json string to be checked * @return true if it is valid if not otherwise */ public static boolean isJsonValid(String json) { return parseObject(json) != null; } /** * Appends value to json * * @param json string json which will be modified * @param value value that will be appended * @return the specified JSON string with appended value */ public static String appendValueToJson(String json, Object value) { return appendValueToJson(json, null, value); } /** * Appends key and/or value to json * * @param json string json which will be modified * @param key key that will be appended * @param value value that will be appended * @return the specified JSON string with appended key and/or value */ public static String appendValueToJson(String json, String key, Object value) { JsonElement jsonElement = parseObject(json); if (jsonElement != null) { if (jsonElement.isJsonPrimitive()) { JsonArray jsonArray = new JsonArray(); jsonArray.add(jsonElement); jsonArray.add(objectToJsonElementTree(value)); return jsonArray.toString(); } else if (jsonElement.isJsonObject()) { if (key == null) { throw new IllegalArgumentException( "to append some value into a JsonObject the 'key' parameter must not be null"); } JsonObject jsonObject = (JsonObject) jsonElement; jsonObject.add(key, objectToJsonElementTree(value)); return jsonObject.toString(); } else if (jsonElement.isJsonArray()) { JsonArray jsonArray = (JsonArray) jsonElement; jsonArray.add(objectToJsonElementTree(value)); return jsonArray.toString(); } } return getJsonElementAsString(jsonElement); } /** * Converts an object into a {@code JsonElement} and search values by their keys * * @param object object you wish to obtain the value * @param keys keys to search on {@code JsonElement} * @return list of occurrences found */ public static List<Object> findValuesByKeys(Object object, String... keys) { JsonElement jsonElement = parseObject(object); List<Object> occurrencesFound = null; if (jsonElement != null && keys != null) { occurrencesFound = new ArrayList<Object>(); for (String key : keys) { deepJsonSearchByKeyToList(key, jsonElement, occurrencesFound); } } return occurrencesFound; } /** * Converts an object into a {@code JsonElement}, search values by their keys and returns first occurrence found * * @param object object you wish to obtain the value * @param keys keys to search on {@code JsonElement} * @return first occurrence found */ public static String findFirstValueByKeys(Object object, String... keys) { List<Object> occurrencesFound = findValuesByKeys(object, keys); if (occurrencesFound != null && !occurrencesFound.isEmpty()) { return getJsonElementAsString(parseObject(occurrencesFound.get(0))); } return null; } /** * Converts an object into a {@code JsonElement}, search values by their keys and returns first not null occurrence found * * @param object object you wish to obtain the value * @param keys keys to search on {@code JsonElement} * @return first not null occurrence found */ public static String findFirstNotNullValueByKeys(Object object, String... keys) { List<Object> occurrencesFound = findValuesByKeys(object, keys); if (occurrencesFound != null && !occurrencesFound.isEmpty()) { for (Object obj : occurrencesFound) { JsonElement jsonElement = parseObject(obj); if (jsonElement != null && !jsonElement.isJsonNull()) { return getJsonElementAsString(jsonElement); } } } return null; } /** * Converts the object to json string without the complexity * of relational hierarchy between them, creating a json "flatten". * * @param object object you wish to converts into a json flatten * @return flattened json */ public static String plainJson(Object object) { JsonElement jsonElement = parseObject(object); if (jsonElement != null) { if (jsonElement.isJsonObject()) { JsonObject jsonObjectFlattened = new JsonObject(); deepJsonObjectSearchToJsonObjectFlattened((JsonObject) jsonElement, jsonObjectFlattened); return jsonObjectFlattened.toString(); } else if (jsonElement.isJsonArray()) { JsonArray jsonArrayFlattened = new JsonArray(); deepJsonArraySearchToJsonArrayFlattened((JsonArray) jsonElement, jsonArrayFlattened); return jsonArrayFlattened.toString(); } } return getJsonElementAsString(jsonElement); } /** * Converts the json string to an list of objects. * <p/> * The parameter {@code flatten} determines if will return a list without the complexity * of relational hierarchy between the objects or not * * @param json string json you wish to converts into a list * @param flatten true to return a flat list, false otherwise * @return list of objects */ public static List<Object> jsonToList(String json, boolean flatten) { List<JsonElement> jsonElementList = jsonToJsonElementList(json, flatten); List<Object> objectList = null; if (jsonElementList != null && !jsonElementList.isEmpty()) { objectList = new ArrayList<Object>(); for (JsonElement jsonElement : jsonElementList) { objectList.add(getJsonElementAsString(jsonElement)); } } return objectList; } /** * Converts the json string to an flattened list of objects * * @param json string json you wish to converts into a list * @return list of objects */ public static List<Object> jsonToList(String json) { return jsonToList(json, true); } //************************** PRIVATE METHODS **************************// private static void deepJsonArraySearchToJsonArrayFlattened(JsonArray jsonArray, JsonArray jsonArrayFlattened) { if (jsonArray == null || jsonArrayFlattened == null) { throw new IllegalArgumentException("JsonArray and/or JsonArrayFlattened parameter(s) must not be null"); } Iterator<JsonElement> iterator = jsonArray.iterator(); while (iterator.hasNext()) { JsonElement value = iterator.next(); if (value.isJsonObject()) { // Creates new flattened JsonObject instance. JsonObject jsonObjectFlattened = new JsonObject(); // Iterates recursively in JsonObject (value), checking content and populating the flattened JsonObject instance. deepJsonObjectSearchToJsonObjectFlattened((JsonObject) value, jsonObjectFlattened); // Adds the flattened JsonObject instance in the flattened JsonArray instance. jsonArrayFlattened.add(jsonObjectFlattened); } else if (value.isJsonArray()) { deepJsonArraySearchToJsonArrayFlattened((JsonArray) value, jsonArrayFlattened); } else { jsonArrayFlattened.add(value); } } } private static void deepJsonObjectSearchToJsonObjectFlattened(JsonObject jsonObject, JsonObject jsonObjectFlattened) { if (jsonObject == null || jsonObjectFlattened == null) { throw new IllegalArgumentException( "JsonObject and/or JsonObjectFlattened parameter(s) must not be null"); } for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { String key = entry.getKey(); JsonElement value = entry.getValue(); if (value.isJsonObject()) { deepJsonObjectSearchToJsonObjectFlattened((JsonObject) value, jsonObjectFlattened); } else if (value.isJsonArray()) { // Creates new flattened JsonArray instance. JsonArray jsonArray = new JsonArray(); // Iterates recursively in JsonArray (value), checking content and populating the flattened JsonArray instance. deepJsonArraySearchToJsonArrayFlattened((JsonArray) value, jsonArray); // Adds the flattened JsonArray instance in the flattened JsonObject instance. jsonObjectFlattened.add(key, jsonArray); } else { // FIXME - WORKAROUND // Attention: A map can not contain duplicate keys. So, the // duplicate key is concatenated with a counter, to avoid data // loss. I could not think of anything better yet. if (jsonObjectFlattened.has(key)) { jsonObjectFlattened.add(key + COUNTER.getAndIncrement(), value); } else { jsonObjectFlattened.add(key, value); } } } } private static void deepJsonSearchToList(JsonElement jsonElement, List<JsonElement> jsonElementList) { if (jsonElement != null && jsonElementList != null) { if (jsonElement.isJsonObject()) { for (Map.Entry<String, JsonElement> entry : ((JsonObject) jsonElement).entrySet()) { deepJsonSearchToList(entry.getValue(), jsonElementList); } } else if (jsonElement.isJsonArray()) { Iterator<JsonElement> iterator = ((JsonArray) jsonElement).iterator(); while (iterator.hasNext()) { deepJsonSearchToList(iterator.next(), jsonElementList); } } else { jsonElementList.add(jsonElement); } } } private static void deepJsonSearchByKeyToList(String desiredKey, JsonElement jsonElement, List<Object> jsonElementList) { if (desiredKey != null && jsonElement != null && jsonElementList != null) { if (jsonElement.isJsonObject()) { for (Map.Entry<String, JsonElement> entry : ((JsonObject) jsonElement).entrySet()) { String key = entry.getKey(); JsonElement value = entry.getValue(); if (key.equalsIgnoreCase(desiredKey)) { jsonElementList.add(getJsonElementAsString(value)); } deepJsonSearchByKeyToList(desiredKey, entry.getValue(), jsonElementList); } } else if (jsonElement.isJsonArray()) { Iterator<JsonElement> iterator = ((JsonArray) jsonElement).iterator(); while (iterator.hasNext()) { deepJsonSearchByKeyToList(desiredKey, iterator.next(), jsonElementList); } } } } private static List<JsonElement> jsonToJsonElementList(String json, boolean flatten) { JsonElement jsonElement = parseObject(json); List<JsonElement> elements = null; if (jsonElement != null) { boolean isJsonObject = jsonElement.isJsonObject(); boolean isJsonArray = jsonElement.isJsonArray(); elements = new ArrayList<JsonElement>(); // Only instances of 'JsonArray' or 'JsonObject' can be flattened if (isJsonArray || isJsonObject) { if (flatten) { deepJsonSearchToList(jsonElement, elements); } else { if (isJsonObject) { for (Map.Entry<String, JsonElement> entry : ((JsonObject) jsonElement).entrySet()) { elements.add(entry.getValue()); } } else { Iterator<JsonElement> iterator = ((JsonArray) jsonElement).iterator(); while (iterator.hasNext()) { elements.add(iterator.next()); } } } } else { elements.add(jsonElement); } } return elements; } private static String getJsonElementAsString(JsonElement jsonElement) { if (jsonElement == null) { return JsonNull.INSTANCE.toString(); } if (jsonElement.isJsonPrimitive()) { return jsonElement.getAsString(); } return jsonElement.toString(); } }