improved support jsonpath

This commit is contained in:
wenshao
2014-10-14 00:12:52 +08:00
parent b2fe2e21cf
commit bb08ef6fd2
3 changed files with 382 additions and 14 deletions
+178 -14
View File
@@ -214,6 +214,74 @@ public class JSONPath implements ObjectSerializer {
skipWhitespace();
if (op == BinaryCompareOperator.IN || op == BinaryCompareOperator.NOT_IN) {
final boolean not = (op == BinaryCompareOperator.NOT_IN);
accept('(');
List<Object> valueList = new ArrayList<Object>();
{
Object value = readValue();
valueList.add(value);
for (;;) {
skipWhitespace();
if (ch != ',') {
break;
}
next();
skipWhitespace();
value = readValue();
valueList.add(value);
}
accept(')');
if (predicateFlag) {
accept(')');
}
accept(']');
}
boolean isInt = true;
boolean isString = true;
for (Object item : valueList) {
if (item == null) {
if (isInt) {
isInt = false;
}
continue;
}
Class<?> clazz = item.getClass();
if (isInt
&& !(clazz == Byte.class || clazz == Short.class || clazz == Integer.class || clazz == Long.class)) {
isInt = false;
}
if (isString && clazz != String.class) {
isString = false;
}
}
if (isInt) {
long[] values = new long[valueList.size()];
for (int i = 0; i < values.length; ++i) {
values[i] = ((Number) valueList.get(i)).longValue();
}
return new IntInSegement(propertyName, values, not);
}
if (isString) {
String[] values = new String[valueList.size()];
valueList.toArray(values);
return new StringInSegement(propertyName, values, not);
}
throw new UnsupportedOperationException();
}
if (ch == '\'' || ch == '"') {
String strValue = readString();
if (predicateFlag) {
@@ -284,19 +352,8 @@ public class JSONPath implements ObjectSerializer {
return new StringCompareFilterAccessSegement(propertyName, strValue, op);
}
if (ch == '-' || ch == '+' || (ch >= '0' && ch <= '9')) {
int beginIndex = pos - 1;
if (ch == '+' || ch == '-') {
next();
}
while (ch >= '0' && ch <= '9') {
next();
}
int endIndex = pos - 1;
String text = path.substring(beginIndex, endIndex);
long value = Long.parseLong(text);
if (isDigitFirst(ch)) {
long value = readLongValue();
if (predicateFlag) {
accept(')');
@@ -344,6 +401,48 @@ public class JSONPath implements ObjectSerializer {
return buildArraySegement(text);
}
protected long readLongValue() {
int beginIndex = pos - 1;
if (ch == '+' || ch == '-') {
next();
}
while (ch >= '0' && ch <= '9') {
next();
}
int endIndex = pos - 1;
String text = path.substring(beginIndex, endIndex);
long value = Long.parseLong(text);
return value;
}
protected Object readValue() {
if (isDigitFirst(ch)) {
return readLongValue();
}
if (ch == '"' || ch == '\'') {
return readString();
}
if (ch == 'n') {
String name = readName();
if ("null".equals(name)) {
return null;
} else {
throw new JSONPathException(path);
}
}
throw new UnsupportedOperationException();
}
static boolean isDigitFirst(char ch) {
return ch == '-' || ch == '+' || (ch >= '0' && ch <= '9');
}
protected BinaryCompareOperator readOp() {
BinaryCompareOperator op = null;
if (ch == '=') {
@@ -383,6 +482,8 @@ public class JSONPath implements ObjectSerializer {
op = BinaryCompareOperator.NOT_LIKE;
} else if ("rlike".equalsIgnoreCase(name)) {
op = BinaryCompareOperator.NOT_RLIKE;
} else if ("in".equalsIgnoreCase(name)) {
op = BinaryCompareOperator.NOT_IN;
} else {
throw new UnsupportedOperationException();
}
@@ -391,6 +492,8 @@ public class JSONPath implements ObjectSerializer {
op = BinaryCompareOperator.LIKE;
} else if ("rlike".equalsIgnoreCase(name)) {
op = BinaryCompareOperator.RLIKE;
} else if ("in".equalsIgnoreCase(name)) {
op = BinaryCompareOperator.IN;
} else {
throw new UnsupportedOperationException();
}
@@ -742,6 +845,67 @@ public class JSONPath implements ObjectSerializer {
}
}
static class IntInSegement extends FilterAccessSegement {
private final String propertyName;
private final long[] values;
private final boolean not;
public IntInSegement(String propertyName, long[] values, boolean not){
this.propertyName = propertyName;
this.values = values;
this.not = not;
}
@Override
public boolean apply(JSONPath path, Object rootObject, Object currentObject, Object item) {
Object propertyValue = path.getPropertyValue(item, propertyName, false);
if (propertyValue == null) {
return false;
}
if (propertyValue instanceof Number) {
long longPropertyValue = ((Number) propertyValue).longValue();
for (long value : values) {
if (value == longPropertyValue) {
return !not;
}
}
}
return not;
}
}
static class StringInSegement extends FilterAccessSegement {
private final String propertyName;
private final String[] values;
private final boolean not;
public StringInSegement(String propertyName, String[] values, boolean not){
this.propertyName = propertyName;
this.values = values;
this.not = not;
}
@Override
public boolean apply(JSONPath path, Object rootObject, Object currentObject, Object item) {
Object propertyValue = path.getPropertyValue(item, propertyName, false);
for (String value : values) {
if (value == propertyValue) {
return !not;
} else if (value != null && value.equals(propertyValue)) {
return !not;
}
}
return not;
}
}
static class IntCompareFilterAccessSegement extends FilterAccessSegement {
private final String propertyName;
@@ -938,7 +1102,7 @@ public class JSONPath implements ObjectSerializer {
}
static enum BinaryCompareOperator {
EQ, NE, GT, GE, LT, LE, LIKE, NOT_LIKE, RLIKE, NOT_RLIKE
EQ, NE, GT, GE, LT, LE, LIKE, NOT_LIKE, RLIKE, NOT_RLIKE, IN, NOT_IN
}
static abstract class FilterAccessSegement implements Segement {
@@ -0,0 +1,102 @@
package com.alibaba.json.bvt.path;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.fastjson.JSONPath;
public class JSONPath_field_access_filter_in_int extends TestCase {
public void test_list_in() throws Exception {
JSONPath path = new JSONPath("[id in (1001)]");
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity(1001, "ljw2083"));
entities.add(new Entity(1002, "wenshao"));
entities.add(new Entity(1003, "yakolee"));
entities.add(new Entity(1004, null));
List<Object> result = (List<Object>) path.eval(entities);
Assert.assertEquals(1, result.size());
Assert.assertSame(entities.get(0), result.get(0));
}
public void test_list_not_in() throws Exception {
JSONPath path = new JSONPath("[id not in (1001)]");
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity(1001, "ljw2083"));
entities.add(new Entity(1002, "wenshao"));
entities.add(new Entity(1003, "yakolee"));
entities.add(new Entity(1004, null));
List<Object> result = (List<Object>) path.eval(entities);
Assert.assertEquals(3, result.size());
Assert.assertSame(entities.get(1), result.get(0));
Assert.assertSame(entities.get(2), result.get(1));
Assert.assertSame(entities.get(3), result.get(2));
}
public void test_list_in_2() throws Exception {
JSONPath path = new JSONPath("[id in (1001, 1003)]");
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity(1001, "ljw2083"));
entities.add(new Entity(1002, "wenshao"));
entities.add(new Entity(1003, "yakolee"));
entities.add(new Entity(1004, null));
List<Object> result = (List<Object>) path.eval(entities);
Assert.assertEquals(2, result.size());
Assert.assertSame(entities.get(0), result.get(0));
Assert.assertSame(entities.get(2), result.get(1));
}
public void test_list_in_3() throws Exception {
JSONPath path = new JSONPath("[id in (1001, 1003, 1004)]");
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity(1001, "ljw2083"));
entities.add(new Entity(1002, "wenshao"));
entities.add(new Entity(1003, "yakolee"));
entities.add(new Entity(1004, null));
List<Object> result = (List<Object>) path.eval(entities);
Assert.assertEquals(3, result.size());
Assert.assertSame(entities.get(0), result.get(0));
Assert.assertSame(entities.get(2), result.get(1));
Assert.assertSame(entities.get(3), result.get(2));
}
public static class Entity {
private Integer id;
private String name;
public Entity(Integer id, String name){
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
@@ -0,0 +1,102 @@
package com.alibaba.json.bvt.path;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.fastjson.JSONPath;
public class JSONPath_field_access_filter_in_string extends TestCase {
public void test_list_in() throws Exception {
JSONPath path = new JSONPath("[name in ('ljw2083')]");
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity(1001, "ljw2083"));
entities.add(new Entity(1002, "wenshao"));
entities.add(new Entity(1003, "yakolee"));
entities.add(new Entity(1004, null));
List<Object> result = (List<Object>) path.eval(entities);
Assert.assertEquals(1, result.size());
Assert.assertSame(entities.get(0), result.get(0));
}
public void test_list_not_in() throws Exception {
JSONPath path = new JSONPath("[name not in ('ljw2083')]");
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity(1001, "ljw2083"));
entities.add(new Entity(1002, "wenshao"));
entities.add(new Entity(1003, "yakolee"));
entities.add(new Entity(1004, null));
List<Object> result = (List<Object>) path.eval(entities);
Assert.assertEquals(3, result.size());
Assert.assertSame(entities.get(1), result.get(0));
Assert.assertSame(entities.get(2), result.get(1));
Assert.assertSame(entities.get(3), result.get(2));
}
public void test_list_in_2() throws Exception {
JSONPath path = new JSONPath("[name in ('ljw2083', 'yakolee')]");
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity(1001, "ljw2083"));
entities.add(new Entity(1002, "wenshao"));
entities.add(new Entity(1003, "yakolee"));
entities.add(new Entity(1004, null));
List<Object> result = (List<Object>) path.eval(entities);
Assert.assertEquals(2, result.size());
Assert.assertSame(entities.get(0), result.get(0));
Assert.assertSame(entities.get(2), result.get(1));
}
public void test_list_in_3() throws Exception {
JSONPath path = new JSONPath("[name in ('ljw2083', 'yakolee',null)]");
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity(1001, "ljw2083"));
entities.add(new Entity(1002, "wenshao"));
entities.add(new Entity(1003, "yakolee"));
entities.add(new Entity(1004, null));
List<Object> result = (List<Object>) path.eval(entities);
Assert.assertEquals(3, result.size());
Assert.assertSame(entities.get(0), result.get(0));
Assert.assertSame(entities.get(2), result.get(1));
Assert.assertSame(entities.get(3), result.get(2));
}
public static class Entity {
private Integer id;
private String name;
public Entity(Integer id, String name){
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}