mirror of
https://gitee.com/dromara/hutool.git
synced 2026-02-09 09:16:26 +08:00
!1412 修复#IDC78B,添加BeanPath方法中对“*”的处理逻辑
Merge pull request !1412 from 王双奇/v5-dev
This commit is contained in:
@@ -192,6 +192,17 @@ public class BeanPath implements Serializable {
|
||||
String patternPart;
|
||||
for (int i = 0; i < length; i++) {
|
||||
patternPart = patternParts.get(i);
|
||||
|
||||
// 支持通配符 * 语法,用于获取集合或数组中所有元素的指定字段
|
||||
if ("*".equals(patternPart)) {
|
||||
// 如果当前对象是集合或数组,且后面还有路径部分,则展开处理
|
||||
if (i < length - 1 && (subBean instanceof Collection || ArrayUtil.isArray(subBean))) {
|
||||
return getByWildcard(subBean, patternParts, i + 1, length);
|
||||
}
|
||||
// 如果 * 是最后一个部分,直接返回当前集合/数组
|
||||
return subBean;
|
||||
}
|
||||
|
||||
subBean = getFieldValue(subBean, patternPart);
|
||||
if (null == subBean) {
|
||||
// 支持表达式的第一个对象为Bean本身(若用户定义表达式$开头,则不做此操作)
|
||||
@@ -206,6 +217,49 @@ public class BeanPath implements Serializable {
|
||||
return subBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理通配符 * 的情况,对集合或数组中的每个元素应用剩余路径
|
||||
*
|
||||
* @param collectionOrArray 集合或数组对象
|
||||
* @param patternParts 完整的表达式分段列表
|
||||
* @param startIndex 剩余路径的起始索引
|
||||
* @param endIndex 路径的结束索引
|
||||
* @return 结果列表
|
||||
*/
|
||||
private Object getByWildcard(final Object collectionOrArray, final List<String> patternParts,
|
||||
final int startIndex, final int endIndex) {
|
||||
final List<Object> results = new ArrayList<>();
|
||||
|
||||
// 获取剩余的路径部分
|
||||
final List<String> remainingParts = patternParts.subList(startIndex, endIndex);
|
||||
|
||||
if (collectionOrArray instanceof Collection) {
|
||||
// 处理集合
|
||||
for (Object item : (Collection<?>) collectionOrArray) {
|
||||
if (item != null) {
|
||||
final Object value = get(remainingParts, item, false);
|
||||
if (value != null) {
|
||||
results.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ArrayUtil.isArray(collectionOrArray)) {
|
||||
// 处理数组
|
||||
final int arrayLength = ArrayUtil.length(collectionOrArray);
|
||||
for (int i = 0; i < arrayLength; i++) {
|
||||
final Object item = ArrayUtil.get(collectionOrArray, i);
|
||||
if (item != null) {
|
||||
final Object value = get(remainingParts, item, false);
|
||||
if (value != null) {
|
||||
results.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results.isEmpty() ? null : results;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Object getFieldValue(final Object bean, final String expression) {
|
||||
if (StrUtil.isBlank(expression)) {
|
||||
|
||||
@@ -139,6 +139,16 @@ public class BeanPathTest {
|
||||
assertEquals("[LOL, KFC, COFFE]", ArrayUtil.toString(myUser.getHobby()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wildcardTest() {
|
||||
// 测试通配符 * 语法
|
||||
final BeanPath pattern = BeanPath.create("userInfo.examInfoDict[*].id");
|
||||
final Object result = pattern.get(tempMap);
|
||||
|
||||
// 应该返回一个包含所有 examInfoDict 元素的 id 的列表
|
||||
assertEquals("[1, 2, 3]", result.toString());
|
||||
}
|
||||
|
||||
@Data
|
||||
static class MyUser {
|
||||
private String[] hobby;
|
||||
|
||||
@@ -50,4 +50,27 @@ public class JSONPathTest {
|
||||
assertNotNull(accountIds);
|
||||
assertArrayEquals(new Long[]{1L, 2L, 3L}, accountIds.toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getByPathWithWildcardTest() {
|
||||
// 测试通配符 [*] 语法
|
||||
JSONObject root = new JSONObject()
|
||||
.put("actionMessage", new JSONObject()
|
||||
.put("alertResults", new JSONArray())
|
||||
.put("decodeFeas", new JSONArray()
|
||||
.put(new JSONObject()
|
||||
.put("body", new JSONObject()
|
||||
.put("lats", new JSONArray()
|
||||
.put(new JSONObject().put("begin", 4260).put("text", "呵呵"))
|
||||
.put(new JSONObject().put("begin", 4260).put("text", "你好 "))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Object byPath = JSONUtil.getByPath(root, "$.actionMessage.decodeFeas[0].body.lats[*].text");
|
||||
assertNotNull(byPath);
|
||||
assertEquals("[呵呵, 你好 ]", byPath.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user