package nl.elastique.poetry.json;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Given a JSON Object { 'root' : { 'key' : 'value' }}
* It can resolve the String "value" when given the path "root.key"
*/
public class JsonPathResolver
{
private final String mPath;
public JsonPathResolver(String path)
{
mPath = path;
}
/**
* Resolve a path for the provided object.
* @param object the object to resolve the path for
* @param path the path to resolve
* @return the found JSONObject on the path
* @throws JsonPathException if processing fails
*/
public static JSONObject resolveObject(JSONObject object, String path) throws JsonPathException
{
boolean is_root_path = (path == null) || path.isEmpty();
if (is_root_path)
{
return object;
}
String[] elements = path.split("\\.");
JSONObject current = object;
int last_index = elements.length - 1;
for (int i = 0; i < elements.length; ++i)
{
Object child_object;
try
{
child_object = current.get(elements[i]);
}
catch (Exception e)
{
throw new JsonPathException(String.format("failed to fetch element \"%s\"", elements[i]));
}
if (JSONArray.class.isAssignableFrom(child_object.getClass()))
{
if (i == last_index)
{
throw new JsonPathException("last element " + elements[i] + " is an array and not an object");
}
else
{
throw new JsonPathException("array element for " + elements[i] + " cannot be parsed at " + path);
}
}
else if (JSONObject.class.isAssignableFrom(child_object.getClass()))
{
if (i == last_index)
{
return (JSONObject)child_object;
}
else
{
current = (JSONObject)child_object;
}
}
else
{
throw new JsonPathException("can't parse element for " + elements[i]
+ " on path " + path
+ " because the type " + child_object.getClass().getName() + " is not supported");
}
}
throw new JsonPathException("json path mapping failed");
}
/**
* Resolve a path for the provided object.
* @param object the object to resolve the path for
* @param path the path to resolve
* @return the found JSONArray on the path
* @throws JsonPathException if processing fails
*/
public static JSONArray resolveArray(JSONObject object, String path) throws JsonPathException
{
boolean is_root_path = (path == null) || path.isEmpty();
if (is_root_path)
{
throw new JsonPathException("root of JSONObject can never be a JSONArray");
}
String[] elements = path.split("\\.");
JSONObject current = object;
int last_index = elements.length - 1;
for (int i = 0; i < elements.length; ++i)
{
Object child_object;
try
{
child_object = current.get(elements[i]);
}
catch (Exception e)
{
throw new JsonPathException(String.format("failed to fetch element \"%s\"", elements[i]));
}
if (JSONArray.class.isAssignableFrom(child_object.getClass()))
{
if (i == last_index)
{
return (JSONArray)child_object;
}
else
{
throw new JsonPathException("array element for " + elements[i] + " is not the last element on the path " + path);
}
}
else if (JSONObject.class.isAssignableFrom(child_object.getClass()))
{
current = (JSONObject)child_object;
}
else
{
throw new JsonPathException("can't parse element for " + elements[i]
+ " on path " + path
+ " because the type " + child_object.getClass().getName() + " is not supported");
}
}
throw new JsonPathException("json path mapping failed");
}
/**
* Resolve the path for the provided object.
* @param object must be a JSONObject or JSONArray
* @return an object that is either a JSONObject or a JSONArray
* @throws JsonPathException when resolving fails
* @deprecated use resolveObject() or resolveArray() instead they are more type-safe
*/
@Deprecated
public Object resolvePath(Object object) throws JsonPathException
{
boolean is_json_object = JSONObject.class.isAssignableFrom(object.getClass());
boolean is_json_array = JSONArray.class.isAssignableFrom(object.getClass());
if (!is_json_object && !is_json_array)
{
throw new IllegalArgumentException("object must be JSONObject or JSONArray");
}
boolean is_root_path = mPath == null || mPath.length() == 0;
if (is_json_array && !is_root_path)
{
throw new IllegalArgumentException("JSONArray can only be parsed at root");
}
if (is_root_path)
{
return object;
}
String[] elements = mPath.split("\\.");
JSONObject current = (JSONObject)object;
int last_index = elements.length - 1;
for (int i = 0; i < elements.length; ++i)
{
Object child_object;
try
{
child_object = current.get(elements[i]);
}
catch (Exception e)
{
throw new JsonPathException(String.format("failed to fetch element \"%s\"", elements[i]));
}
if (JSONArray.class.isAssignableFrom(child_object.getClass()))
{
if (i == last_index)
{
return child_object;
}
else
{
throw new JsonPathException("array element for " + elements[i] + " is not the last element on the path " + mPath);
}
}
else if (JSONObject.class.isAssignableFrom(child_object.getClass()))
{
current = (JSONObject)child_object;
}
else
{
throw new JsonPathException("can't parse element for " + elements[i]
+ " on path " + mPath
+ " because the type " + child_object.getClass().getName() + " is not supported");
}
}
return current;
}
}