JSONPathTypedMultiIndexes.java
package com.alibaba.fastjson2;
import com.alibaba.fastjson2.util.TypeUtils;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.time.ZoneId;
import java.util.List;
final class JSONPathTypedMultiIndexes
extends JSONPathTypedMulti {
final JSONPath prefix;
final JSONPath[] indexPaths;
final int[] indexes;
final int maxIndex;
final boolean duplicate;
JSONPathTypedMultiIndexes(
JSONPath[] paths,
JSONPath prefix,
JSONPath[] indexPaths,
Type[] types,
String[] formats,
long[] pathFeatures,
ZoneId zoneId,
long features
) {
super(paths, types, formats, pathFeatures, zoneId, features);
this.prefix = prefix;
this.indexPaths = indexPaths;
int[] indexes = new int[paths.length];
for (int i = 0; i < indexPaths.length; i++) {
JSONPathSingleIndex indexPath = (JSONPathSingleIndex) indexPaths[i];
indexes[i] = indexPath.index;
}
this.indexes = indexes;
boolean duplicate = false;
int maxIndex = -1;
for (int i = 0; i < indexes.length; i++) {
int index = indexes[i];
if (i == 0) {
maxIndex = index;
} else {
maxIndex = Math.max(maxIndex, index);
}
for (int j = 0; j < indexes.length && !duplicate; j++) {
if (j != i && index == indexes[j]) {
duplicate = true;
break;
}
}
}
this.duplicate = duplicate;
this.maxIndex = maxIndex;
}
@Override
public Object eval(Object root) {
Object[] array = new Object[paths.length];
Object object = root;
if (prefix != null) {
object = prefix.eval(root);
}
if (object == null) {
return array;
}
if (object instanceof List) {
List list = (List) object;
for (int i = 0; i < indexes.length; i++) {
int index = indexes[i];
Object result = index < list.size() ? list.get(index) : null;
Type type = types[i];
try {
if (result != null && result.getClass() != type) {
if (type == Long.class) {
result = TypeUtils.toLong(result);
} else if (type == BigDecimal.class) {
result = TypeUtils.toBigDecimal(result);
} else if (type == String[].class) {
result = TypeUtils.toStringArray(result);
} else {
result = TypeUtils.cast(result, type);
}
}
array[i] = result;
} catch (Exception e) {
if (!ignoreError(i)) {
throw new JSONException("jsonpath eval path, path : " + paths[i] + ", msg : " + e.getMessage(), e);
}
}
}
} else {
for (int i = 0; i < paths.length; i++) {
JSONPath jsonPath = indexPaths[i];
Type type = types[i];
try {
Object result = jsonPath.eval(object);
if (result != null && result.getClass() != type) {
if (type == Long.class) {
result = TypeUtils.toLong(result);
} else if (type == BigDecimal.class) {
result = TypeUtils.toBigDecimal(result);
} else if (type == String[].class) {
result = TypeUtils.toStringArray(result);
} else {
result = TypeUtils.cast(result, type);
}
}
array[i] = result;
} catch (Exception e) {
if (!ignoreError(i)) {
throw new JSONException("jsonpath eval path, path : " + paths[i] + ", msg : " + e.getMessage(), e);
}
}
}
}
return array;
}
@Override
public Object extract(JSONReader jsonReader) {
if (jsonReader.nextIfNull()) {
return new Object[indexes.length];
}
if (prefix instanceof JSONPathSingleName) {
JSONPathSingleName prefixName = (JSONPathSingleName) prefix;
long prefixNameHash = prefixName.nameHashCode;
if (!jsonReader.nextIfObjectStart()) {
throw new JSONException(jsonReader.info("illegal input, expect '[', but " + jsonReader.current()));
}
while (!jsonReader.nextIfObjectEnd()) {
long nameHashCode = jsonReader.readFieldNameHashCode();
boolean match = nameHashCode == prefixNameHash;
if (!match) {
jsonReader.skipValue();
continue;
}
break;
}
if (jsonReader.nextIfNull()) {
return new Object[indexes.length];
}
} else if (prefix instanceof JSONPathSingleIndex) {
int index = ((JSONPathSingleIndex) prefix).index;
int max = jsonReader.startArray();
for (int i = 0; i < index && i < max; i++) {
jsonReader.skipValue();
}
if (jsonReader.nextIfNull()) {
return null;
}
} else if (prefix != null) {
Object object = jsonReader.readAny();
return eval(object);
}
int max = jsonReader.startArray();
Object[] array = new Object[indexes.length];
for (int i = 0; i <= maxIndex && i < max; ++i) {
if ((!jsonReader.jsonb) && jsonReader.nextIfArrayEnd()) {
break;
}
Integer index = null;
for (int j = 0; j < indexes.length; j++) {
if (indexes[j] == i) {
index = j;
break;
}
}
if (index == null) {
jsonReader.skipValue();
continue;
}
Type type = types[index];
Object value;
try {
value = jsonReader.read(type);
} catch (Exception e) {
if (!ignoreError(index)) {
throw e;
}
value = null;
}
array[index] = value;
if (!duplicate) {
continue;
}
for (int j = index + 1; j < indexes.length; j++) {
if (indexes[j] == i) {
Type typeJ = types[j];
Object valueJ;
if (typeJ == type) {
valueJ = value;
} else {
valueJ = TypeUtils.cast(value, typeJ);
}
array[j] = valueJ;
}
}
}
return array;
}
}