shade.com.alibaba.fastjson2.JSONPathParser Maven / Gradle / Ivy
package com.alibaba.fastjson2;
import com.alibaba.fastjson2.util.Fnv;
import com.alibaba.fastjson2.util.TypeUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import static com.alibaba.fastjson2.JSONReader.EOI;
class JSONPathParser {
final String path;
final JSONReader jsonReader;
boolean dollar;
boolean lax;
boolean strict;
int segmentIndex;
JSONPathSegment first;
JSONPathSegment second;
List segments;
int filterNests;
boolean negative;
public JSONPathParser(String str) {
this.jsonReader = JSONReader.of(this.path = str, JSONPath.PARSE_CONTEXT);
if (jsonReader.ch == 'l' && jsonReader.nextIfMatchIdent('l', 'a', 'x')) {
lax = true;
} else if (jsonReader.ch == 's' && jsonReader.nextIfMatchIdent('s', 't', 'r', 'i', 'c', 't')) {
strict = true;
}
if (jsonReader.ch == '-') {
jsonReader.next();
negative = true;
}
if (jsonReader.ch == '$') {
jsonReader.next();
dollar = true;
}
}
JSONPath parse(JSONPath.Feature... features) {
if (dollar && jsonReader.ch == EOI) {
if (negative) {
return new JSONPathSingle(JSONPathFunction.FUNC_NEGATIVE, path);
} else {
return JSONPath.RootPath.INSTANCE;
}
}
if (jsonReader.ch == 'e' && jsonReader.nextIfMatchIdent('e', 'x', 'i', 's', 't', 's')) {
if (!jsonReader.nextIfMatch('(')) {
throw new JSONException("syntax error " + path);
}
if (jsonReader.ch == '@') {
jsonReader.next();
if (!jsonReader.nextIfMatch('.')) {
throw new JSONException("syntax error " + path);
}
}
char ch = jsonReader.ch;
JSONPathSegment segment;
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' || ch == '@' || Character.isIdeographic(ch)) {
segment = parseProperty();
} else {
throw new JSONException("syntax error " + path);
}
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException("syntax error " + path);
}
return new JSONPathTwoSegment(path, segment, JSONPathFunction.FUNC_EXISTS);
}
while (jsonReader.ch != EOI) {
final JSONPathSegment segment;
char ch = jsonReader.ch;
if (ch == '.') {
jsonReader.next();
segment = parseProperty();
} else if (jsonReader.ch == '[') {
segment = parseArrayAccess();
} else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' || Character.isIdeographic(ch)) {
segment = parseProperty();
} else if (ch == '?') {
if (dollar && segmentIndex == 0) {
first = JSONPathSegment.RootSegment.INSTANCE;
segmentIndex++;
}
jsonReader.next();
segment = parseFilter();
} else if (ch == '@') {
jsonReader.next();
segment = JSONPathSegment.SelfSegment.INSTANCE;
} else {
throw new JSONException("not support " + ch);
}
if (segmentIndex == 0) {
first = segment;
} else if (segmentIndex == 1) {
second = segment;
} else if (segmentIndex == 2) {
segments = new ArrayList<>();
segments.add(first);
segments.add(second);
segments.add(segment);
} else {
segments.add(segment);
}
segmentIndex++;
}
if (negative) {
if (segmentIndex == 1) {
second = JSONPathFunction.FUNC_NEGATIVE;
} else if (segmentIndex == 2) {
segments = new ArrayList<>();
segments.add(first);
segments.add(second);
segments.add(JSONPathFunction.FUNC_NEGATIVE);
} else {
segments.add(JSONPathFunction.FUNC_NEGATIVE);
}
segmentIndex++;
}
if (segmentIndex == 1) {
if (first instanceof JSONPathSegmentName) {
return new JSONPathSingleName(path, (JSONPathSegmentName) first, features);
}
if (first instanceof JSONPathSegmentIndex) {
JSONPathSegmentIndex firstIndex = (JSONPathSegmentIndex) first;
if (firstIndex.index >= 0) {
return new JSONPathSingleIndex(path, firstIndex, features);
}
}
return new JSONPathSingle(first, path, features);
}
if (segmentIndex == 2) {
return new JSONPathTwoSegment(path, first, second, features);
}
return new JSONPathMulti(path, segments, features);
}
private JSONPathSegment parseArrayAccess() {
jsonReader.next();
JSONPathSegment segment;
switch (jsonReader.ch) {
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': {
int index = jsonReader.readInt32Value();
boolean last = false;
if (jsonReader.ch == ':') {
jsonReader.next();
if (jsonReader.ch == ']') {
segment = new JSONPathSegment.RangeIndexSegment(index, index >= 0 ? Integer.MAX_VALUE : 0);
} else {
int end = jsonReader.readInt32Value();
segment = new JSONPathSegment.RangeIndexSegment(index, end);
}
} else if (jsonReader.isNumber() || (last = jsonReader.nextIfMatchIdent('l', 'a', 's', 't'))) {
List list = new ArrayList<>();
list.add(index);
if (last) {
list.add(-1);
jsonReader.nextIfComma();
}
while (true) {
if (jsonReader.isNumber()) {
index = jsonReader.readInt32Value();
list.add(index);
} else if (jsonReader.nextIfMatchIdent('l', 'a', 's', 't')) {
list.add(-1);
jsonReader.nextIfComma();
} else {
break;
}
}
int[] indics = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
indics[i] = list.get(i);
}
segment = new JSONPathSegment.MultiIndexSegment(indics);
} else {
segment = JSONPathSegmentIndex.of(index);
}
break;
}
case '*':
jsonReader.next();
segment = JSONPathSegment.AllSegment.INSTANCE_ARRAY;
break;
case ':': {
jsonReader.next();
int end = jsonReader.ch == ']' ? 0 : jsonReader.readInt32Value();
if (end > 0) {
segment = new JSONPathSegment.RangeIndexSegment(0, end);
} else {
segment = new JSONPathSegment.RangeIndexSegment(Integer.MIN_VALUE, end);
}
break;
}
case '"':
case '\'':
String name = jsonReader.readString();
if (jsonReader.current() == ']') {
segment = new JSONPathSegmentName(name, Fnv.hashCode64(name));
} else if (jsonReader.isString()) {
List names = new ArrayList<>();
names.add(name);
do {
names.add(jsonReader.readString());
} while (jsonReader.isString());
String[] nameArray = new String[names.size()];
names.toArray(nameArray);
segment = new JSONPathSegment.MultiNameSegment(nameArray);
} else {
throw new JSONException("TODO : " + jsonReader.current());
}
break;
case '?':
jsonReader.next();
segment = parseFilter();
break;
case 'r': {
String fieldName = jsonReader.readFieldNameUnquote();
if ("randomIndex".equals(fieldName)) {
if (jsonReader.nextIfMatch('(')
&& jsonReader.nextIfMatch(')')
&& jsonReader.ch == (']')) {
segment = JSONPathSegment.RandomIndexSegment.INSTANCE;
break;
}
}
throw new JSONException("not support : " + fieldName);
}
case 'l': {
String fieldName = jsonReader.readFieldNameUnquote();
if ("last".equals(fieldName)) {
segment = JSONPathSegmentIndex.of(-1);
} else {
throw new JSONException("not support : " + fieldName);
}
break;
}
case '(': {
jsonReader.next();
if (jsonReader.nextIfMatch('@') && jsonReader.nextIfMatch('.')) {
String fieldName = jsonReader.readFieldNameUnquote();
switch (fieldName) {
case "length":
case "size": {
int index = jsonReader.readInt32Value();
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException("not support : " + fieldName);
}
if (index > 0) {
throw new JSONException("not support : " + fieldName);
} else {
segment = JSONPathSegmentIndex.of(index);
}
break;
}
default:
throw new JSONException("not support : " + path);
}
} else {
throw new JSONException("not support : " + path);
}
break;
}
default:
throw new JSONException("TODO : " + jsonReader.current());
}
if (jsonReader.ch == '&' || jsonReader.ch == '|' || jsonReader.ch == 'a' || jsonReader.ch == 'o') {
filterNests--;
segment = parseFilterRest(segment);
}
while (filterNests > 0) {
jsonReader.next();
filterNests--;
}
if (!jsonReader.nextIfArrayEnd()) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
return segment;
}
private JSONPathSegment parseProperty() {
final JSONPathSegment segment;
if (jsonReader.ch == '*') {
jsonReader.next();
segment = JSONPathSegment.AllSegment.INSTANCE;
} else if (jsonReader.ch == '.') {
jsonReader.next();
if (jsonReader.ch == '*') {
jsonReader.next();
segment = new JSONPathSegment.CycleNameSegment("*", Fnv.hashCode64("*"));
} else {
long hashCode = jsonReader.readFieldNameHashCodeUnquote();
String name = jsonReader.getFieldName();
segment = new JSONPathSegment.CycleNameSegment(name, hashCode);
}
} else {
boolean isNum = jsonReader.isNumber();
long hashCode = jsonReader.readFieldNameHashCodeUnquote();
String name = jsonReader.getFieldName();
if (isNum) {
final int length = name.length();
if (length <= 9) {
for (int i = 0; i < length; ++i) {
char ch = name.charAt(i);
if (ch < '0' || ch > '9') {
break;
}
}
}
}
if (jsonReader.ch == '(') {
jsonReader.next();
switch (name) {
case "length":
case "size":
segment = JSONPathSegment.LengthSegment.INSTANCE;
break;
case "keys":
segment = JSONPathSegment.KeysSegment.INSTANCE;
break;
case "values":
segment = JSONPathSegment.ValuesSegment.INSTANCE;
break;
case "entrySet":
segment = JSONPathSegment.EntrySetSegment.INSTANCE;
break;
case "min":
segment = JSONPathSegment.MinSegment.INSTANCE;
break;
case "max":
segment = JSONPathSegment.MaxSegment.INSTANCE;
break;
case "sum":
segment = JSONPathSegment.SumSegment.INSTANCE;
break;
case "type":
segment = JSONPathFunction.FUNC_TYPE;
break;
case "floor":
segment = JSONPathFunction.FUNC_FLOOR;
break;
case "ceil":
case "ceiling":
segment = JSONPathFunction.FUNC_CEIL;
break;
case "double":
segment = JSONPathFunction.FUNC_DOUBLE;
break;
case "abs":
segment = JSONPathFunction.FUNC_ABS;
break;
case "lower":
segment = JSONPathFunction.FUNC_LOWER;
break;
case "upper":
segment = JSONPathFunction.FUNC_UPPER;
break;
case "trim":
segment = JSONPathFunction.FUNC_TRIM;
break;
case "negative":
segment = JSONPathFunction.FUNC_NEGATIVE;
break;
case "first":
segment = JSONPathFunction.FUNC_FIRST;
break;
case "last":
segment = JSONPathFunction.FUNC_LAST;
break;
case "index":
if (jsonReader.isNumber()) {
Number number = jsonReader.readNumber();
if (number instanceof BigDecimal) {
BigDecimal decimal = (BigDecimal) number;
decimal = decimal.stripTrailingZeros();
if (decimal.scale() != 0) {
segment = new JSONPathFunction(new JSONPathFunction.IndexDecimal(decimal));
break;
}
BigInteger unscaledValue = decimal.unscaledValue();
if (unscaledValue.compareTo(TypeUtils.BIGINT_INT64_MIN) >= 0
&& unscaledValue.compareTo(TypeUtils.BIGINT_INT64_MAX) <= 0) {
number = unscaledValue.longValue();
} else {
number = unscaledValue;
}
}
if (number instanceof Integer
|| number instanceof Long
) {
long longValue = number.longValue();
segment = new JSONPathFunction(new JSONPathFunction.IndexInt(longValue));
break;
}
} else if (jsonReader.isString()) {
String indexValue = jsonReader.readString();
segment = new JSONPathFunction(new JSONPathFunction.IndexString(indexValue));
break;
}
throw new JSONException("not support syntax, path : " + path);
default:
throw new JSONException("not support syntax, path : " + path);
}
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException("not support syntax, path : " + path);
}
} else {
segment = new JSONPathSegmentName(name, hashCode);
}
}
return segment;
}
JSONPathSegment parseFilterRest(JSONPathSegment segment) {
boolean and;
switch (jsonReader.ch) {
case '&':
jsonReader.next();
if (!jsonReader.nextIfMatch('&')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
and = true;
break;
case '|':
jsonReader.next();
if (!jsonReader.nextIfMatch('|')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
and = false;
break;
case 'a':
case 'A': {
String fieldName = jsonReader.readFieldNameUnquote();
if (!"and".equalsIgnoreCase(fieldName)) {
throw new JSONException("syntax error : " + fieldName);
}
and = true;
break;
}
case 'o':
case 'O': {
String fieldName = jsonReader.readFieldNameUnquote();
if (!"or".equalsIgnoreCase(fieldName)) {
throw new JSONException("syntax error : " + fieldName);
}
and = false;
break;
}
default:
throw new JSONException("TODO : " + jsonReader.ch);
}
JSONPathSegment right = parseFilter();
if (segment instanceof JSONPathFilter.GroupFilter) {
JSONPathFilter.GroupFilter group = (JSONPathFilter.GroupFilter) segment;
group.filters.add(((JSONPathFilter) right).setAnd(and));
return group;
}
List filters = new ArrayList<>();
filters.add((JSONPathFilter) segment);
if (right instanceof JSONPathFilter.GroupFilter) {
JSONPathFilter.GroupFilter group = (JSONPathFilter.GroupFilter) right;
List groupFilters = group.filters;
if (groupFilters != null && groupFilters.size() > 0) {
for (int i = 0; i < groupFilters.size(); ++i) {
JSONPathFilter filter = groupFilters.get(i);
if (i == 0) {
filter.setAnd(and);
}
filters.add(filter);
}
}
} else {
filters.add(((JSONPathFilter) right).setAnd(and));
}
return new JSONPathFilter.GroupFilter(filters);
}
JSONPathSegment parseFilter() {
boolean parentheses = jsonReader.nextIfMatch('(');
if (parentheses && filterNests > 0) {
filterNests++;
}
boolean at = jsonReader.ch == '@';
if (at) {
jsonReader.next();
} else if (jsonReader.nextIfMatchIdent('e', 'x', 'i', 's', 't', 's')) {
if (!jsonReader.nextIfMatch('(')) {
throw new JSONException(jsonReader.info("exists"));
}
if (jsonReader.nextIfMatch('@')) {
if (jsonReader.nextIfMatch('.')) {
long hashCode = jsonReader.readFieldNameHashCodeUnquote();
String fieldName = jsonReader.getFieldName();
if (jsonReader.nextIfMatch(')')) {
if (parentheses) {
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
}
return new JSONPathFilter.NameExistsFilter(fieldName, hashCode);
} else if (jsonReader.ch == '.') {
List names = new ArrayList<>();
names.add(fieldName);
do {
jsonReader.next();
fieldName = jsonReader.readFieldNameUnquote();
names.add(fieldName);
} while (jsonReader.ch == '.');
if (jsonReader.nextIfMatch(')')) {
if (parentheses) {
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
}
}
return new JSONPathFilter.NamesExistsFilter(names);
}
}
}
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
boolean starts = jsonReader.nextIfMatchIdent('s', 't', 'a', 'r', 't', 's');
boolean ends = (!starts) && jsonReader.nextIfMatchIdent('e', 'n', 'd', 's');
if ((at && (starts || ends)) || (jsonReader.ch != '.' && !JSONReader.isFirstIdentifier(jsonReader.ch))) {
if (jsonReader.nextIfMatch('(')) {
filterNests++;
filterNests++;
return parseFilter();
}
if (!at) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
JSONPathFilter.Operator operator;
if (starts || ends) {
jsonReader.readFieldNameHashCodeUnquote();
String fieldName = jsonReader.getFieldName();
if (!"with".equalsIgnoreCase(fieldName)) {
throw new JSONException("not support operator : " + fieldName);
}
operator = starts ? JSONPathFilter.Operator.STARTS_WITH : JSONPathFilter.Operator.ENDS_WITH;
} else {
operator = JSONPath.parseOperator(jsonReader);
}
JSONPathSegment segment = null;
if (jsonReader.isNumber()) {
Number number = jsonReader.readNumber();
if (number instanceof Integer || number instanceof Long) {
segment = new JSONPathFilter.NameIntOpSegment(null, 0, null, null, null, operator, number.longValue());
}
} else if (jsonReader.isString()) {
String string = jsonReader.readString();
switch (operator) {
case STARTS_WITH:
segment = new JSONPathFilter.StartsWithSegment(null, 0, string);
break;
case ENDS_WITH:
segment = new JSONPathFilter.EndsWithSegment(null, 0, string);
break;
default:
throw new JSONException("syntax error, " + string);
}
}
while (jsonReader.ch == '&' || jsonReader.ch == '|') {
filterNests--;
segment = parseFilterRest(segment);
}
if (segment != null) {
if (parentheses) {
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
}
return segment;
}
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
if (at) {
jsonReader.next();
}
long hashCode = jsonReader.readFieldNameHashCodeUnquote();
String fieldName = jsonReader.getFieldName();
if (parentheses) {
if (jsonReader.nextIfMatch(')')) {
if (filterNests > 0) {
filterNests--;
}
return new JSONPathFilter.NameExistsFilter(fieldName, hashCode);
}
}
String functionName = null;
long[] hashCode2 = null;
String[] fieldName2 = null;
while (jsonReader.ch == '.') {
jsonReader.next();
long hash = jsonReader.readFieldNameHashCodeUnquote();
String str = jsonReader.getFieldName();
if (jsonReader.ch == '(') {
functionName = str;
break;
}
if (hashCode2 == null) {
hashCode2 = new long[]{hash};
fieldName2 = new String[]{str};
} else {
hashCode2 = Arrays.copyOf(hashCode2, hashCode2.length + 1);
hashCode2[hashCode2.length - 1] = hash;
fieldName2 = Arrays.copyOf(fieldName2, fieldName2.length + 1);
fieldName2[fieldName2.length - 1] = str;
}
}
JSONPathFilter.Operator operator = null;
Function function = null;
if (jsonReader.ch == '(') {
if (functionName == null) {
functionName = fieldName;
fieldName = null;
}
switch (functionName) {
case "type":
hashCode = 0;
function = JSONPathFunction.TypeFunction.INSTANCE;
break;
case "size":
hashCode = 0;
function = JSONPathFunction.SizeFunction.INSTANCE;
break;
case "contains":
hashCode = 0;
operator = JSONPathFilter.Operator.CONTAINS;
break;
default:
throw new JSONException("syntax error, function not support " + fieldName);
}
if (function != null) {
jsonReader.next();
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException("syntax error, function " + functionName);
}
}
}
if (operator == null) {
operator = JSONPath.parseOperator(jsonReader);
}
switch (operator) {
case REG_MATCH:
case RLIKE:
case NOT_RLIKE: {
String regex;
boolean ignoreCase;
if (jsonReader.isString()) {
regex = jsonReader.readString();
ignoreCase = false;
} else {
regex = jsonReader.readPattern();
ignoreCase = jsonReader.nextIfMatch('i');
}
Pattern pattern = ignoreCase
? Pattern.compile(regex, Pattern.CASE_INSENSITIVE)
: Pattern.compile(regex);
JSONPathSegment segment = new JSONPathFilter.NameRLikeSegment(fieldName, hashCode, pattern, operator == JSONPathFilter.Operator.NOT_RLIKE);
if (jsonReader.ch == '&' || jsonReader.ch == '|' || jsonReader.ch == 'a' || jsonReader.ch == 'o') {
filterNests--;
segment = parseFilterRest(segment);
}
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
return segment;
}
case IN:
case NOT_IN: {
if (jsonReader.ch != '(') {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
jsonReader.next();
JSONPathSegment segment;
if (jsonReader.isString()) {
List list = new ArrayList<>();
while (jsonReader.isString()) {
list.add(jsonReader.readString());
}
String[] strArray = new String[list.size()];
list.toArray(strArray);
segment = new JSONPathFilter.NameStringInSegment(
fieldName,
hashCode,
strArray,
operator == JSONPathFilter.Operator.NOT_IN
);
} else if (jsonReader.isNumber()) {
List list = new ArrayList<>();
while (jsonReader.isNumber()) {
list.add(jsonReader.readNumber());
}
long[] values = new long[list.size()];
for (int i = 0; i < list.size(); i++) {
values[i] = list.get(i).longValue();
}
segment = new JSONPathFilter.NameIntInSegment(fieldName, hashCode, fieldName2, hashCode2, function, values, operator == JSONPathFilter.Operator.NOT_IN);
} else {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
if (jsonReader.ch == '&' || jsonReader.ch == '|' || jsonReader.ch == 'a' || jsonReader.ch == 'o') {
filterNests--;
segment = parseFilterRest(segment);
}
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
return segment;
}
case CONTAINS: {
if (jsonReader.ch != '(') {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
jsonReader.next();
JSONPathSegment segment;
if (jsonReader.isString()) {
List list = new ArrayList<>();
while (jsonReader.isString()) {
list.add(jsonReader.readString());
}
String[] strArray = new String[list.size()];
list.toArray(strArray);
segment = new JSONPathFilter.NameStringContainsSegment(
fieldName,
hashCode,
fieldName2,
hashCode2,
strArray,
false
);
} else if (jsonReader.isNumber()) {
List list = new ArrayList<>();
while (jsonReader.isNumber()) {
list.add(jsonReader.readNumber());
}
long[] values = new long[list.size()];
for (int i = 0; i < list.size(); i++) {
values[i] = list.get(i).longValue();
}
segment = new JSONPathFilter.NameLongContainsSegment(
fieldName,
hashCode,
fieldName2,
hashCode2,
values,
false
);
} else {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
return segment;
}
case BETWEEN:
case NOT_BETWEEN: {
JSONPathSegment segment;
if (jsonReader.isNumber()) {
Number begin = jsonReader.readNumber();
String and = jsonReader.readFieldNameUnquote();
if (!"and".equalsIgnoreCase(and)) {
throw new JSONException("syntax error, " + and);
}
Number end = jsonReader.readNumber();
segment = new JSONPathFilter.NameIntBetweenSegment(fieldName, hashCode, begin.longValue(), end.longValue(), operator == JSONPathFilter.Operator.NOT_BETWEEN);
} else {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
if (parentheses) {
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
}
return segment;
}
default:
break;
}
JSONPathSegment segment = null;
switch (jsonReader.ch) {
case '-':
case '+':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': {
Number number = jsonReader.readNumber();
if (number instanceof Integer || number instanceof Long) {
segment = new JSONPathFilter.NameIntOpSegment(fieldName, hashCode, fieldName2, hashCode2, function, operator, number.longValue());
} else if (number instanceof BigDecimal) {
segment = new JSONPathFilter.NameDecimalOpSegment(fieldName, hashCode, operator, (BigDecimal) number);
} else {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
break;
}
case '"':
case '\'': {
String strVal = jsonReader.readString();
int p0 = strVal.indexOf('%');
if (p0 == -1) {
if (operator == JSONPathFilter.Operator.LIKE) {
operator = JSONPathFilter.Operator.EQ;
} else if (operator == JSONPathFilter.Operator.NOT_LIKE) {
operator = JSONPathFilter.Operator.NE;
}
}
if (operator == JSONPathFilter.Operator.LIKE || operator == JSONPathFilter.Operator.NOT_LIKE) {
String[] items = strVal.split("%");
String startsWithValue = null;
String endsWithValue = null;
String[] containsValues = null;
if (p0 == 0) {
if (strVal.charAt(strVal.length() - 1) == '%') {
containsValues = new String[items.length - 1];
System.arraycopy(items, 1, containsValues, 0, containsValues.length);
} else {
endsWithValue = items[items.length - 1];
if (items.length > 2) {
containsValues = new String[items.length - 2];
System.arraycopy(items, 1, containsValues, 0, containsValues.length);
}
}
} else if (strVal.charAt(strVal.length() - 1) == '%') {
if (items.length == 1) {
startsWithValue = items[0];
} else {
containsValues = items;
}
} else {
if (items.length == 1) {
startsWithValue = items[0];
} else if (items.length == 2) {
startsWithValue = items[0];
endsWithValue = items[1];
} else {
startsWithValue = items[0];
endsWithValue = items[items.length - 1];
containsValues = new String[items.length - 2];
System.arraycopy(items, 1, containsValues, 0, containsValues.length);
}
}
segment = new JSONPathFilter.NameMatchFilter(
fieldName,
hashCode,
startsWithValue,
endsWithValue,
containsValues,
operator == JSONPathFilter.Operator.NOT_LIKE
);
} else {
segment = new JSONPathFilter.NameStringOpSegment(fieldName, hashCode, fieldName2, hashCode2, function, operator, strVal);
}
break;
}
case 't': {
String ident = jsonReader.readFieldNameUnquote();
if ("true".equalsIgnoreCase(ident)) {
segment = new JSONPathFilter.NameIntOpSegment(fieldName, hashCode, fieldName2, hashCode2, function, operator, 1);
break;
}
break;
}
case 'f': {
String ident = jsonReader.readFieldNameUnquote();
if ("false".equalsIgnoreCase(ident)) {
segment = new JSONPathFilter.NameIntOpSegment(fieldName, hashCode, fieldName2, hashCode2, function, operator, 0);
break;
}
break;
}
case '[': {
JSONArray array = jsonReader.read(JSONArray.class);
segment = new JSONPathFilter.NameArrayOpSegment(fieldName, hashCode, fieldName2, hashCode2, function, operator, array);
break;
}
case '{': {
JSONObject object = jsonReader.read(JSONObject.class);
segment = new JSONPathFilter.NameObjectOpSegment(fieldName, hashCode, fieldName2, hashCode2, function, operator, object);
break;
}
case 'n':
boolean nextNull = jsonReader.nextIfNull();
if (nextNull) {
segment = new JSONPathFilter.NameIsNull(fieldName, hashCode, fieldName2, hashCode2, function);
break;
}
throw new JSONException(jsonReader.info("jsonpath syntax error"));
default:
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
if (jsonReader.ch == '&' || jsonReader.ch == '|' || jsonReader.ch == 'a' || jsonReader.ch == 'o') {
filterNests--;
segment = parseFilterRest(segment);
}
if (parentheses) {
if (!jsonReader.nextIfMatch(')')) {
throw new JSONException(jsonReader.info("jsonpath syntax error"));
}
}
return segment;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy