improve jsonpath support

This commit is contained in:
wenshao
2014-10-14 21:17:29 +08:00
parent fb57673aa7
commit ba7f25f063
2 changed files with 125 additions and 49 deletions
+107 -49
View File
@@ -47,19 +47,25 @@ public class JSONPath implements ObjectSerializer {
this.serializeConfig = serializeConfig;
}
protected void init() {
if (pathSegments != null) {
return;
}
if ("*".equals(path)) {
this.pathSegments = new Segement[] { WildCardSegement.instance };
} else {
JSONPathParser parser = new JSONPathParser(path);
this.pathSegments = parser.explain();
}
}
public Object eval(Object rootObject) {
if (rootObject == null) {
return null;
}
if (pathSegments == null) {
if ("*".equals(path)) {
this.pathSegments = new Segement[] { WildCardSegement.instance };
} else {
JSONPathParser parser = new JSONPathParser(path);
this.pathSegments = parser.explain();
}
}
init();
Object currentObject = rootObject;
for (int i = 0; i < pathSegments.length; ++i) {
@@ -68,7 +74,33 @@ public class JSONPath implements ObjectSerializer {
return currentObject;
}
public int size(Object rootObject) {
if (rootObject == null) {
return -1;
}
init();
Object currentObject = rootObject;
for (int i = 0; i < pathSegments.length; ++i) {
currentObject = pathSegments[i].eval(this, rootObject, currentObject);
}
return evalSize(currentObject);
}
public static Object eval(Object rootObject, String path) {
JSONPath jsonpath = compile(path);
return jsonpath.eval(rootObject);
}
public static int size(Object rootObject, String path) {
JSONPath jsonpath = compile(path);
Object result = jsonpath.eval(rootObject);
return jsonpath.evalSize(result);
}
public static JSONPath compile(String path) {
JSONPath jsonpath = pathCache.get(path);
if (jsonpath == null) {
jsonpath = new JSONPath(path);
@@ -77,7 +109,7 @@ public class JSONPath implements ObjectSerializer {
jsonpath = pathCache.get(path);
}
}
return jsonpath.eval(rootObject);
return jsonpath;
}
public String getPath() {
@@ -723,29 +755,8 @@ public class JSONPath implements ObjectSerializer {
public final static SizeSegement instance = new SizeSegement();
@SuppressWarnings("rawtypes")
public Integer eval(JSONPath path, Object rootObject, Object currentObject) {
if (currentObject == null) {
return 0;
}
if (currentObject instanceof Collection) {
return ((Collection) currentObject).size();
}
if (currentObject instanceof Object[]) {
return ((Object[]) currentObject).length;
}
if (currentObject.getClass().isArray()) {
return Array.getLength(currentObject);
}
if (currentObject instanceof Map) {
return ((Map) currentObject).size();
}
throw new UnsupportedOperationException();
return path.evalSize(currentObject);
}
}
@@ -1247,15 +1258,7 @@ public class JSONPath implements ObjectSerializer {
protected Collection<Object> getPropertyValues(final Object currentObject) {
final Class<?> currentClass = currentObject.getClass();
JavaBeanSerializer beanSerializer = null;
{
ObjectSerializer serializer = serializeConfig.getObjectWriter(currentClass);
if (serializer instanceof JavaBeanSerializer) {
beanSerializer = (JavaBeanSerializer) serializer;
} else if (serializer instanceof ASMJavaBeanSerializer) {
beanSerializer = ((ASMJavaBeanSerializer) serializer).getJavaBeanSerializer();
}
}
JavaBeanSerializer beanSerializer = getJavaBeanSerializer(currentClass);
if (beanSerializer != null) {
try {
@@ -1286,15 +1289,7 @@ public class JSONPath implements ObjectSerializer {
final Class<?> currentClass = currentObject.getClass();
JavaBeanSerializer beanSerializer = null;
{
ObjectSerializer serializer = serializeConfig.getObjectWriter(currentClass);
if (serializer instanceof JavaBeanSerializer) {
beanSerializer = (JavaBeanSerializer) serializer;
} else if (serializer instanceof ASMJavaBeanSerializer) {
beanSerializer = ((ASMJavaBeanSerializer) serializer).getJavaBeanSerializer();
}
}
JavaBeanSerializer beanSerializer = getJavaBeanSerializer(currentClass);
if (beanSerializer != null) {
try {
return beanSerializer.getFieldValue(currentObject, propertyName);
@@ -1319,6 +1314,69 @@ public class JSONPath implements ObjectSerializer {
throw new JSONPathException("jsonpath error, path " + path + ", segement " + propertyName);
}
protected JavaBeanSerializer getJavaBeanSerializer(final Class<?> currentClass) {
JavaBeanSerializer beanSerializer = null;
{
ObjectSerializer serializer = serializeConfig.getObjectWriter(currentClass);
if (serializer instanceof JavaBeanSerializer) {
beanSerializer = (JavaBeanSerializer) serializer;
} else if (serializer instanceof ASMJavaBeanSerializer) {
beanSerializer = ((ASMJavaBeanSerializer) serializer).getJavaBeanSerializer();
}
}
return beanSerializer;
}
@SuppressWarnings("rawtypes")
int evalSize(Object currentObject) {
if (currentObject == null) {
return -1;
}
if (currentObject instanceof Collection) {
return ((Collection) currentObject).size();
}
if (currentObject instanceof Object[]) {
return ((Object[]) currentObject).length;
}
if (currentObject.getClass().isArray()) {
return Array.getLength(currentObject);
}
if (currentObject instanceof Map) {
int count = 0;
for (Object value : ((Map) currentObject).values()) {
if (value != null) {
count++;
}
}
return count;
}
JavaBeanSerializer beanSerializer = getJavaBeanSerializer(currentObject.getClass());
if (beanSerializer == null) {
return -1;
}
try {
List<Object> values = beanSerializer.getFieldValues(currentObject);
int count = 0;
for (int i = 0; i < values.size(); ++i) {
if (values.get(i) != null) {
count++;
}
}
return count;
} catch (Exception e) {
throw new JSONException("evalSize error : " + path, e);
}
}
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
throws IOException {
serializer.write(path);
@@ -0,0 +1,18 @@
package com.alibaba.fastjson.support.odps.udf;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPath;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.aliyun.odps.udf.UDF;
public class JSONSize extends UDF {
public JSONSize(){
SerializeConfig.getGlobalInstance().setAsmEnable(false);
}
public Long evaluate(String jsonString, String path) throws Exception {
Object json = JSON.parse(jsonString);
return Long.valueOf(JSONPath.size(json, path));
}
}