You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
5.1 KiB
196 lines
5.1 KiB
package com.jayway.jsonassert.impl; |
|
|
|
import com.jayway.jsonassert.InvalidPathException; |
|
import com.jayway.jsonassert.JSONReader; |
|
import org.json.simple.JSONArray; |
|
import org.json.simple.JSONObject; |
|
import org.json.simple.parser.JSONParser; |
|
import org.json.simple.parser.ParseException; |
|
|
|
import java.io.IOException; |
|
import java.io.Reader; |
|
import java.util.LinkedList; |
|
import java.util.List; |
|
import java.util.Map; |
|
|
|
import static org.apache.commons.lang.Validate.notNull; |
|
|
|
/** |
|
* User: kalle stenflo |
|
* Date: 1/20/11 |
|
* Time: 4:27 PM |
|
*/ |
|
public class JSONReaderImpl implements JSONReader { |
|
|
|
|
|
private static final JSONParser JSON_PARSER = new JSONParser(); |
|
|
|
private Object root; |
|
private String currentPath; |
|
|
|
|
|
public static synchronized JSONReader parse(Reader reader) throws java.text.ParseException, IOException { |
|
try { |
|
return new JSONReaderImpl(JSON_PARSER.parse(reader)); |
|
} catch (IOException e) { |
|
throw e; |
|
} catch (ParseException e) { |
|
throw new java.text.ParseException(e.getMessage(), e.getPosition()); |
|
} |
|
} |
|
|
|
public static synchronized JSONReader parse(String jsonDoc) throws java.text.ParseException { |
|
try { |
|
return new JSONReaderImpl(JSON_PARSER.parse(jsonDoc)); |
|
} catch (ParseException e) { |
|
throw new java.text.ParseException(e.getMessage(), e.getPosition()); |
|
} |
|
} |
|
|
|
private JSONReaderImpl(Object root) { |
|
notNull(root, "root object can not be null"); |
|
this.root = root; |
|
} |
|
|
|
|
|
/** |
|
* {@inheritDoc} |
|
*/ |
|
public boolean hasJsonPath(String path) { |
|
boolean contains = true; |
|
try { |
|
get(path); |
|
} catch (InvalidPathException e) { |
|
contains = false; |
|
} |
|
return contains; |
|
} |
|
|
|
/** |
|
* {@inheritDoc} |
|
*/ |
|
public boolean isNull(String path) { |
|
return (null == get(path)); |
|
} |
|
|
|
/** |
|
* {@inheritDoc} |
|
*/ |
|
public Object get(String path) { |
|
return getByPath(Object.class, path); |
|
} |
|
|
|
/** |
|
* {@inheritDoc} |
|
*/ |
|
public String getString(String path) { |
|
return getByPath(String.class, path); |
|
} |
|
|
|
/** |
|
* {@inheritDoc} |
|
*/ |
|
public Long getLong(String path) { |
|
return getByPath(Long.class, path); |
|
} |
|
|
|
/** |
|
* {@inheritDoc} |
|
*/ |
|
public Double getDouble(String path) { |
|
return getByPath(Double.class, path); |
|
} |
|
|
|
/** |
|
* {@inheritDoc} |
|
*/ |
|
public Boolean getBoolean(String path) { |
|
return getByPath(Boolean.class, path); |
|
} |
|
|
|
/** |
|
* {@inheritDoc} |
|
*/ |
|
public <T> List<T> getList(String path) { |
|
return getByPath(List.class, path); |
|
} |
|
|
|
/** |
|
* {@inheritDoc} |
|
*/ |
|
public Map getMap(String path) { |
|
return getByPath(Map.class, path); |
|
} |
|
|
|
|
|
//------------------------------------------------------------ |
|
// |
|
// private methods |
|
// |
|
//------------------------------------------------------------ |
|
|
|
|
|
private <T> T getByPath(Class<T> clazz, String stringPath) { |
|
currentPath = ""; |
|
Object current = this.root; |
|
JSONPath path = new JSONPath(stringPath); |
|
|
|
while (path.hasMoreFragments()) { |
|
|
|
JSONPathFragment fragment = path.nextFragment(); |
|
|
|
currentPath = fragment.appendToPath(currentPath); |
|
|
|
if (fragment.isArrayIndex()) { |
|
current = toArray(current).get(fragment.getArrayIndex()); |
|
} else if (fragment.isArrayWildcard()) { |
|
current = getContainerValue(current, path.nextFragment()); |
|
} else { |
|
current = getContainerValue(current, fragment); |
|
} |
|
} |
|
return clazz.cast(current); |
|
} |
|
|
|
private JSONArray toArray(Object array) { |
|
return (JSONArray) array; |
|
} |
|
|
|
private JSONObject toDocument(Object document) { |
|
return (JSONObject) document; |
|
} |
|
|
|
/** |
|
* Extracts a field from a given container. If the given container |
|
* is an Array the field specified represents a field in the objects |
|
* contained in the array. Values from all instances of this field |
|
* will be returned in a List |
|
* |
|
* @param container a json document or array |
|
* @param fragment the field to extract from the document alt. the documents contained in the array |
|
* @return a single field value or a List of fields |
|
*/ |
|
private Object getContainerValue(Object container, JSONPathFragment fragment) { |
|
Object result; |
|
|
|
if (container instanceof JSONArray) { |
|
List list = new LinkedList(); |
|
for (Object doc : toArray(container)) { |
|
list.add(getContainerValue(doc, fragment)); |
|
} |
|
result = list; |
|
|
|
} else if (container instanceof JSONObject) { |
|
JSONObject document = toDocument(container); |
|
|
|
if (!document.containsKey(fragment.value())) { |
|
throw new InvalidPathException("Invalid path element: " + currentPath + " <=="); |
|
} |
|
|
|
result = document.get(fragment.value()); |
|
} else { |
|
throw new InvalidPathException("Invalid path element: " + currentPath + " <=="); |
|
} |
|
return result; |
|
} |
|
}
|
|
|