/*******************************************************************************
* Copyright (c) 2010-2015 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.skalli.commons;
import java.text.MessageFormat;
import org.apache.commons.lang.StringUtils;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
/**
* Utilities for parsing and navigating in JSON data structures.
*/
public final class JSONUtils {
private JSONUtils() {
}
/**
* Parses the given serialized JSON and returns the result as
* generic JSON element.
*
* @param s the string to parse.
* @return the JSON element corresponding to the passed in text.
*
* @throws JsonParseException if the specified text is not valid JSON.
*/
public static JsonElement jsonFromString(String s) throws JsonParseException {
return new JsonParser().parse(s);
}
/**
* Parses the given serialized JSON and returns the result as
* generic JSON object.
*
* @param s the string to parse.
* @return the JSON object corresponding to the passed in text.
*
* @throws JsonParseException if the specified text is not valid JSON,
* or the result is not a JSON object.
*/
public static JsonObject jsonObjectFromString(String s) throws JsonParseException {
JsonElement parsed = jsonFromString(s);
if (!parsed.isJsonObject()) {
throw new JsonParseException(MessageFormat.format("Not a JSON object: ''{0}''", s));
}
return parsed.getAsJsonObject();
}
/**
* Parses the given serialized JSON and returns the result as
* generic JSON array.
*
* @param s the string to parse.
* @return the JSON array corresponding to the passed in text.
*
* @throws JsonParseException if the specified text is not valid JSON,
* or the result is not a JSON array.
*/
public static JsonArray jsonArrayFromString(String s) throws JsonParseException {
JsonElement parsed = jsonFromString(s);
if (!parsed.isJsonArray()) {
throw new JsonParseException(MessageFormat.format("Not a JSON array: ''{0}''", s));
}
return parsed.getAsJsonArray();
}
/**
* Returns the integer value of a given attribute of a JSON object.
* Supports nested attributes like "outer.inner.attribute".
*
* @param json a serialized JSON string,
* @param attribute the attribute to return the value for.
*
* @return the integer value of the attribute, or <code>null</code> if the specified
* attribute does not exist. If the value is a string, its numerical representationm
* is returned, if possible.
*/
public static Integer getInteger(String json, String attribute) {
JsonPrimitive value = getPrimitive(jsonObjectFromString(json), attribute);
if (value != null) {
if (value.isNumber()) {
return value.getAsInt();
}
if (value.isString()) {
try {
return Integer.parseInt(value.getAsString());
} catch (NumberFormatException e) {
// ignore and return null
}
}
}
return null;
}
/**
* Returns the string value of a given attribute of a JSON object.
* Supports nested attributes like "outer.inner.attribute".
*
* @param json serialized JSON string.
* @param attribute the attribute to return the value for.
*
* @return the string value of the attribute, or <code>null</code> if the specified
* attribute does not exist.
*/
public static String getString(String json, String attribute) {
JsonPrimitive value = getPrimitive(jsonObjectFromString(json), attribute);
return value != null && (value.isString() || value.isNumber() || value.isBoolean())? value.getAsString() : null;
}
/**
* Navigates into a JSON object following a dot notation, e.g.
* "outer.inner.attribute".
*
* @param root the JSON object to start with.
* @param path the path to navigate through the JSON object tree.
*
* @return the value as generic JSON primitive (string, number etc.).
*/
public static JsonPrimitive getPrimitive(JsonObject root, String path) {
JsonElement value = getValue(root, path);
return value != null && value.isJsonPrimitive()? value.getAsJsonPrimitive() : null;
}
/**
* Navigates into a JSON object following a dot notation, e.g.
* "outer.inner.attribute".
*
* @param root the JSON object to start with.
* @param path the path to navigate through the JSON object tree.
*
* @return the value as generic JSON element.
*/
public static JsonElement getValue(JsonObject root, String path) {
if (StringUtils.isBlank(path)) {
return root;
}
String[] split = path.split("\\."); //$NON-NLS-1$
int i = 0;
JsonObject next = root;
while (i < split.length - 1) {
if (!next.has(split[i])) {
return null;
}
JsonElement elem = next.get(split[i]);
if (!elem.isJsonObject()) {
return null;
}
next = elem.getAsJsonObject();
++i;
}
return next.get(split[i]);
}
}