Skip to content

Commit

Permalink
improved jsonpath support, fix #3629
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Jan 31, 2021
1 parent b584203 commit a383623
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 6 deletions.
63 changes: 57 additions & 6 deletions src/main/java/com/alibaba/fastjson/JSONPath.java
Expand Up @@ -913,12 +913,21 @@ Segment readSegement() {
next();
}
}
if (ch == '*') {
if (ch == '*' || (deep && ch == '[')) {
boolean objectOnly = ch == '[';
if (!isEOF()) {
next();
}

return deep ? WildCardSegment.instance_deep : WildCardSegment.instance;
if (deep) {
if (objectOnly) {
return WildCardSegment.instance_deep_objectOnly;
} else {
return WildCardSegment.instance_deep;
}
} else {
return WildCardSegment.instance;
}
}

if (isDigitFirst(ch)) {
Expand Down Expand Up @@ -2618,13 +2627,16 @@ public void extract(JSONPath path, DefaultJSONParser parser, Context context) {

static class WildCardSegment implements Segment {
private boolean deep;
private boolean objectOnly;

private WildCardSegment(boolean deep) {
private WildCardSegment(boolean deep, boolean objectOnly) {
this.deep = deep;
this.objectOnly = objectOnly;
}

public final static WildCardSegment instance = new WildCardSegment(false);
public final static WildCardSegment instance_deep = new WildCardSegment(true);
public final static WildCardSegment instance = new WildCardSegment(false, false);
public final static WildCardSegment instance_deep = new WildCardSegment(true, false);
public final static WildCardSegment instance_deep_objectOnly = new WildCardSegment(true, true);

public Object eval(JSONPath path, Object rootObject, Object currentObject) {
if (!deep) {
Expand All @@ -2641,7 +2653,11 @@ public void extract(JSONPath path, DefaultJSONParser parser, Context context) {
Object object = parser.parse();
if (deep) {
List<Object> values = new ArrayList<Object>();
path.deepGetPropertyValues(object, values);
if (objectOnly) {
path.deepGetObjects(object, values);
} else {
path.deepGetPropertyValues(object, values);
}
context.object = values;
return;
}
Expand Down Expand Up @@ -3625,6 +3641,41 @@ protected Collection<Object> getPropertyValues(final Object currentObject) {
throw new UnsupportedOperationException();
}

protected void deepGetObjects(final Object currentObject, List<Object> outValues) {
final Class<?> currentClass = currentObject.getClass();

JavaBeanSerializer beanSerializer = getJavaBeanSerializer(currentClass);

Collection collection = null;
if (beanSerializer != null) {
try {
collection = beanSerializer.getFieldValues(currentObject);
outValues.add(currentObject);
} catch (Exception e) {
throw new JSONPathException("jsonpath error, path " + path, e);
}
} else if (currentObject instanceof Map) {
outValues.add(currentObject);
Map map = (Map) currentObject;
collection = map.values();
} else if (currentObject instanceof Collection) {
collection = (Collection) currentObject;
}

if (collection != null) {
for (Object fieldValue : collection) {
if (fieldValue == null || ParserConfig.isPrimitive2(fieldValue.getClass())) {
// skip
} else {
deepGetObjects(fieldValue, outValues);
}
}
return;
}

throw new UnsupportedOperationException(currentClass.getName());
}

protected void deepGetPropertyValues(final Object currentObject, List<Object> outValues) {
final Class<?> currentClass = currentObject.getClass();

Expand Down
42 changes: 42 additions & 0 deletions src/test/java/com/alibaba/json/bvt/issue_3600/Issue3629.java
@@ -0,0 +1,42 @@
package com.alibaba.json.bvt.issue_3600;

import com.alibaba.fastjson.JSONPath;
import java.util.List;
import junit.framework.TestCase;

public class Issue3629 extends TestCase {
public void test_for_issue() throws Exception {
String text1 = "[\n" +
" {\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"category\": \"reference\",\n" +
" \"price\": 8.95,\n" +
" \"title\": \"Sayings of the Century\"\n" +
" },\n" +
" {\n" +
" \"author\": \"Evelyn Waugh\",\n" +
" \"category\": \"fiction\",\n" +
" \"price\": 12.99,\n" +
" \"title\": \"Sword of Honour\"\n" +
" },\n" +
" {\n" +
" \"author\": \"Herman Melville\",\n" +
" \"category\": \"fiction\",\n" +
" \"isbn\": \"0-553-21311-3\",\n" +
" \"price\": 8.99,\n" +
" \"title\": \"Moby Dick\"\n" +
" },\n" +
" {\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"category\": \"fiction\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"price\": 22.99,\n" +
" \"title\": \"The Lord of the Rings\"\n" +
" }\n" +
"]";


List<Object> extract = (List) JSONPath.extract(text1, "$..[?(@.price < 10)]");
assertEquals(2, extract.size());
}
}

0 comments on commit a383623

Please sign in to comment.