mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-24 18:04:54 +08:00
add BeanPath
This commit is contained in:
parent
f9165d06b7
commit
1023af3e40
@ -46,7 +46,7 @@ import java.util.*;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
* @since 4.0.6
|
* @since 4.0.6
|
||||||
*/
|
*/
|
||||||
public class BeanPath implements Serializable {
|
public class BeanPathOld implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,8 +79,8 @@ public class BeanPath implements Serializable {
|
|||||||
* @param expression 表达式
|
* @param expression 表达式
|
||||||
* @return BeanPath
|
* @return BeanPath
|
||||||
*/
|
*/
|
||||||
public static BeanPath of(final String expression) {
|
public static BeanPathOld of(final String expression) {
|
||||||
return new BeanPath(expression);
|
return new BeanPathOld(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,7 +88,7 @@ public class BeanPath implements Serializable {
|
|||||||
*
|
*
|
||||||
* @param expression 表达式
|
* @param expression 表达式
|
||||||
*/
|
*/
|
||||||
public BeanPath(final String expression) {
|
public BeanPathOld(final String expression) {
|
||||||
init(expression);
|
init(expression);
|
||||||
}
|
}
|
||||||
|
|
@ -355,7 +355,7 @@ public class BeanUtil {
|
|||||||
* @param bean Bean对象,支持Map、List、Collection、Array
|
* @param bean Bean对象,支持Map、List、Collection、Array
|
||||||
* @param expression 表达式,例如:person.friend[5].name
|
* @param expression 表达式,例如:person.friend[5].name
|
||||||
* @return Bean属性值,bean为{@code null}或者express为空,返回{@code null}
|
* @return Bean属性值,bean为{@code null}或者express为空,返回{@code null}
|
||||||
* @see BeanPath#get(Object)
|
* @see BeanPathOld#get(Object)
|
||||||
* @since 3.0.7
|
* @since 3.0.7
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@ -363,7 +363,7 @@ public class BeanUtil {
|
|||||||
if (null == bean || StrUtil.isBlank(expression)) {
|
if (null == bean || StrUtil.isBlank(expression)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (T) BeanPath.of(expression).get(bean);
|
return (T) BeanPathOld.of(expression).get(bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -372,11 +372,11 @@ public class BeanUtil {
|
|||||||
* @param bean Bean对象,支持Map、List、Collection、Array
|
* @param bean Bean对象,支持Map、List、Collection、Array
|
||||||
* @param expression 表达式,例如:person.friend[5].name
|
* @param expression 表达式,例如:person.friend[5].name
|
||||||
* @param value 属性值
|
* @param value 属性值
|
||||||
* @see BeanPath#get(Object)
|
* @see BeanPathOld#get(Object)
|
||||||
* @since 4.0.6
|
* @since 4.0.6
|
||||||
*/
|
*/
|
||||||
public static void setProperty(final Object bean, final String expression, final Object value) {
|
public static void setProperty(final Object bean, final String expression, final Object value) {
|
||||||
BeanPath.of(expression).set(bean, value);
|
BeanPathOld.of(expression).set(bean, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------- mapToBean
|
// --------------------------------------------------------------------------------------------- mapToBean
|
||||||
|
@ -99,7 +99,7 @@ public class DynaBean implements Cloneable, Serializable {
|
|||||||
return (T) CollUtil.get((Collection<?>) bean, Integer.parseInt(fieldName));
|
return (T) CollUtil.get((Collection<?>) bean, Integer.parseInt(fieldName));
|
||||||
} catch (final NumberFormatException e) {
|
} catch (final NumberFormatException e) {
|
||||||
// 非数字,see pr#254@Gitee
|
// 非数字,see pr#254@Gitee
|
||||||
return (T) CollUtil.map((Collection<?>) bean, (beanEle) -> BeanUtil.getFieldValue(beanEle, fieldName), false);
|
return (T) CollUtil.map((Collection<?>) bean, (beanEle) -> DynaBean.of(beanEle).get(fieldName), false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName);
|
final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName);
|
||||||
|
@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.core.bean.path;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
|
import org.dromara.hutool.core.bean.path.node.NameNode;
|
||||||
|
import org.dromara.hutool.core.bean.path.node.Node;
|
||||||
|
import org.dromara.hutool.core.bean.path.node.NodeFactory;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
|
import org.dromara.hutool.core.text.CharUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean路径表达式,用于获取多层嵌套Bean中的字段值或Bean对象<br>
|
||||||
|
* 根据给定的表达式,查找Bean中对应的属性值对象。 表达式分为两种:
|
||||||
|
* <ol>
|
||||||
|
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||||
|
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||||
|
* </ol>
|
||||||
|
* <p>
|
||||||
|
* 表达式栗子:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* persion
|
||||||
|
* persion.name
|
||||||
|
* persons[3]
|
||||||
|
* person.friends[5].name
|
||||||
|
* ['person']['friends'][5]['name']
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
* @since 6.0.0
|
||||||
|
*/
|
||||||
|
public class BeanPath implements Node, Iterator<BeanPath> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表达式边界符号数组
|
||||||
|
*/
|
||||||
|
private static final char[] EXP_CHARS = {CharUtil.DOT, CharUtil.BRACKET_START, CharUtil.BRACKET_END};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建Bean路径
|
||||||
|
*
|
||||||
|
* @param expression 表达式
|
||||||
|
* @return BeanPath
|
||||||
|
*/
|
||||||
|
public static BeanPath of(final String expression) {
|
||||||
|
return new BeanPath(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Node node;
|
||||||
|
private final String child;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param expression 表达式
|
||||||
|
*/
|
||||||
|
public BeanPath(final String expression) {
|
||||||
|
final int length = expression.length();
|
||||||
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
char c;
|
||||||
|
boolean isNumStart = false;// 下标标识符开始
|
||||||
|
boolean isInWrap = false; //标识是否在引号内
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
c = expression.charAt(i);
|
||||||
|
if ('\'' == c) {
|
||||||
|
// 结束
|
||||||
|
isInWrap = (!isInWrap);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isInWrap && ArrayUtil.contains(EXP_CHARS, c)) {
|
||||||
|
// 处理边界符号
|
||||||
|
if (CharUtil.BRACKET_END == c) {
|
||||||
|
// 中括号(数字下标)结束
|
||||||
|
if (!isNumStart) {
|
||||||
|
throw new IllegalArgumentException(StrUtil.format("Bad expression '{}':{}, we find ']' but no '[' !", expression, i));
|
||||||
|
}
|
||||||
|
isNumStart = false;
|
||||||
|
// 中括号结束加入下标
|
||||||
|
} else {
|
||||||
|
if (isNumStart) {
|
||||||
|
// 非结束中括号情况下发现起始中括号报错(中括号未关闭)
|
||||||
|
throw new IllegalArgumentException(StrUtil.format("Bad expression '{}':{}, we find '[' but no ']' !", expression, i));
|
||||||
|
} else if (CharUtil.BRACKET_START == c) {
|
||||||
|
// 数字下标开始
|
||||||
|
isNumStart = true;
|
||||||
|
}
|
||||||
|
// 每一个边界符之前的表达式是一个完整的KEY,开始处理KEY
|
||||||
|
}
|
||||||
|
if (builder.length() > 0) {
|
||||||
|
this.node = NodeFactory.createNode(builder.toString());
|
||||||
|
// 如果以[结束,表示后续还有表达式,需保留'[',如name[0]
|
||||||
|
this.child = StrUtil.nullIfEmpty(expression.substring(c == CharUtil.BRACKET_START ? i : i + 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非边界符号,追加字符
|
||||||
|
builder.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最后的节点
|
||||||
|
if (isNumStart) {
|
||||||
|
throw new IllegalArgumentException(StrUtil.format("Bad expression '{}':{}, we find '[' but no ']' !", expression, length - 1));
|
||||||
|
} else {
|
||||||
|
this.node = NodeFactory.createNode(builder.toString());
|
||||||
|
this.child = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取节点
|
||||||
|
*
|
||||||
|
* @return 节点
|
||||||
|
*/
|
||||||
|
public Node getNode() {
|
||||||
|
return this.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取子表达式
|
||||||
|
*
|
||||||
|
* @return 子表达式
|
||||||
|
*/
|
||||||
|
public String getChild() {
|
||||||
|
return this.child;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return null != this.child;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BeanPath next() {
|
||||||
|
return new BeanPath(this.child);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue(final Object bean) {
|
||||||
|
Object value = this.node.getValue(bean);
|
||||||
|
if (hasNext()) {
|
||||||
|
value = next().getValue(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValue(Object bean, final Object value) {
|
||||||
|
Object parentBean;
|
||||||
|
BeanPath beanPath = this;
|
||||||
|
while (beanPath.hasNext()) {
|
||||||
|
parentBean = bean;
|
||||||
|
bean = beanPath.node.getValue(bean);
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
if(null == bean && beanPath.hasNext()){
|
||||||
|
final Node node = beanPath.node;
|
||||||
|
if(node instanceof NameNode){
|
||||||
|
bean = ((NameNode) node).isNumber() ? new ArrayList<>() : new HashMap<>();
|
||||||
|
}else{
|
||||||
|
throw new IllegalArgumentException("Invalid node to create sub bean");
|
||||||
|
}
|
||||||
|
beanPath.node.setValue(parentBean, bean);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.log(beanPath, bean, value);
|
||||||
|
beanPath.node.setValue(bean, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BeanPath{" +
|
||||||
|
"node=" + node +
|
||||||
|
", child='" + child + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.core.bean.path.node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 空节点
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
*/
|
||||||
|
public class EmptyNode implements Node {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单例
|
||||||
|
*/
|
||||||
|
public static EmptyNode INSTANCE = new EmptyNode();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue(final Object bean) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValue(final Object bean, final Object value) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.core.bean.path.node;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
|
import org.dromara.hutool.core.bean.BeanUtil;
|
||||||
|
import org.dromara.hutool.core.collection.CollUtil;
|
||||||
|
import org.dromara.hutool.core.convert.Convert;
|
||||||
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
|
import org.dromara.hutool.core.text.CharUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
import org.dromara.hutool.core.text.split.SplitUtil;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表节点
|
||||||
|
* [num0,num1,num2...]模式或者['key0','key1']模式
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
*/
|
||||||
|
public class ListNode implements Node{
|
||||||
|
|
||||||
|
final List<String> names;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表节点
|
||||||
|
* @param expression 表达式
|
||||||
|
*/
|
||||||
|
public ListNode(final String expression) {
|
||||||
|
this.names = SplitUtil.splitTrim(expression, StrUtil.COMMA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Object getValue(final Object bean) {
|
||||||
|
final List<String> names = this.names;
|
||||||
|
|
||||||
|
if (bean instanceof Collection) {
|
||||||
|
return CollUtil.getAny((Collection<?>) bean, Convert.convert(int[].class, names));
|
||||||
|
} else if (ArrayUtil.isArray(bean)) {
|
||||||
|
return ArrayUtil.getAny(bean, Convert.convert(int[].class, names));
|
||||||
|
} else {
|
||||||
|
final String[] unWrappedNames = getUnWrappedNames(names);
|
||||||
|
if (bean instanceof Map) {
|
||||||
|
// 只支持String为key的Map
|
||||||
|
return MapUtil.getAny((Map<String, ?>) bean, unWrappedNames);
|
||||||
|
} else {
|
||||||
|
final Map<String, Object> map = BeanUtil.beanToMap(bean);
|
||||||
|
return MapUtil.getAny(map, unWrappedNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValue(final Object bean, final Object value) {
|
||||||
|
throw new UnsupportedOperationException("Can not set value to multi names.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.names.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将列表中的name,去除单引号
|
||||||
|
* @param names name列表
|
||||||
|
* @return 处理后的name列表
|
||||||
|
*/
|
||||||
|
private String[] getUnWrappedNames(final List<String> names){
|
||||||
|
final String[] unWrappedNames = new String[names.size()];
|
||||||
|
for (int i = 0; i < unWrappedNames.length; i++) {
|
||||||
|
unWrappedNames[i] = StrUtil.unWrap(names.get(i), CharUtil.SINGLE_QUOTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return unWrappedNames;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.core.bean.path.node;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.bean.DynaBean;
|
||||||
|
import org.dromara.hutool.core.math.NumberUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理名称节点或序号节点,如:
|
||||||
|
* <ul>
|
||||||
|
* <li>name</li>
|
||||||
|
* <li>1</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
*/
|
||||||
|
public class NameNode implements Node {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param name 节点名
|
||||||
|
*/
|
||||||
|
public NameNode(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为数字节点
|
||||||
|
*
|
||||||
|
* @return 是否为数字节点
|
||||||
|
*/
|
||||||
|
public boolean isNumber() {
|
||||||
|
return NumberUtil.isInteger(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue(final Object bean) {
|
||||||
|
if ("$".equals(name)) {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
return DynaBean.of(bean).get(this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValue(final Object bean, final Object value) {
|
||||||
|
DynaBean.of(bean).set(this.name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.core.bean.path.node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean路径节点接口
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
*/
|
||||||
|
public interface Node {
|
||||||
|
/**
|
||||||
|
* 获取Bean对应节点的值
|
||||||
|
*
|
||||||
|
* @param bean bean对象
|
||||||
|
* @return 节点值
|
||||||
|
*/
|
||||||
|
Object getValue(Object bean);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置节点值
|
||||||
|
*
|
||||||
|
* @param bean bean对象
|
||||||
|
* @param value 节点值
|
||||||
|
*/
|
||||||
|
void setValue(Object bean, Object value);
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.core.bean.path.node;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.text.CharUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点简单工厂
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 6.0.0
|
||||||
|
*/
|
||||||
|
public class NodeFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据表达式创建对应的节点
|
||||||
|
*
|
||||||
|
* @param expression 表达式
|
||||||
|
* @return 节点
|
||||||
|
*/
|
||||||
|
public static Node createNode(final String expression) {
|
||||||
|
if (StrUtil.isEmpty(expression)) {
|
||||||
|
return EmptyNode.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.contains(expression, CharUtil.COLON)) {
|
||||||
|
return new RangeNode(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.contains(expression, CharUtil.COMMA)) {
|
||||||
|
return new ListNode(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NameNode(expression);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.core.bean.path.node;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
|
import org.dromara.hutool.core.collection.CollUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
import org.dromara.hutool.core.text.split.SplitUtil;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [start:end:step] 模式节点
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
*/
|
||||||
|
public class RangeNode implements Node {
|
||||||
|
|
||||||
|
private final int start;
|
||||||
|
private final int end;
|
||||||
|
private final int step;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param expression 表达式
|
||||||
|
*/
|
||||||
|
public RangeNode(final String expression) {
|
||||||
|
final List<String> parts = SplitUtil.splitTrim(expression, StrUtil.COLON);
|
||||||
|
this.start = Integer.parseInt(parts.get(0));
|
||||||
|
this.end = Integer.parseInt(parts.get(1));
|
||||||
|
int step = 1;
|
||||||
|
if (3 == parts.size()) {
|
||||||
|
step = Integer.parseInt(parts.get(2));
|
||||||
|
}
|
||||||
|
this.step = step;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue(final Object bean) {
|
||||||
|
if (bean instanceof Collection) {
|
||||||
|
return CollUtil.sub((Collection<?>) bean, this.start, this.end, this.step);
|
||||||
|
} else if (ArrayUtil.isArray(bean)) {
|
||||||
|
return ArrayUtil.sub(bean, this.start, this.end, this.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnsupportedOperationException("Can not get range value for: " + bean.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValue(final Object bean, final Object value) {
|
||||||
|
throw new UnsupportedOperationException("Can not set value with step name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return StrUtil.format("[{}:{}:{}]", this.start, this.end, this.step);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean路径节点
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
*/
|
||||||
|
package org.dromara.hutool.core.bean.path.node;
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean路径,通过路径表达式查找或设置对象或子对象中的值
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 6.0.0
|
||||||
|
*/
|
||||||
|
package org.dromara.hutool.core.bean.path;
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.map;
|
package org.dromara.hutool.core.map;
|
||||||
|
|
||||||
import org.dromara.hutool.core.bean.BeanPath;
|
import org.dromara.hutool.core.bean.BeanPathOld;
|
||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
import org.dromara.hutool.core.bean.BeanUtil;
|
||||||
import org.dromara.hutool.core.bean.copier.CopyOptions;
|
import org.dromara.hutool.core.bean.copier.CopyOptions;
|
||||||
import org.dromara.hutool.core.collection.set.SetUtil;
|
import org.dromara.hutool.core.collection.set.SetUtil;
|
||||||
@ -423,12 +423,12 @@ public class Dict extends CustomKeyMap<String, Object> implements TypeGetter<Str
|
|||||||
* @param <T> 目标类型
|
* @param <T> 目标类型
|
||||||
* @param expression 表达式
|
* @param expression 表达式
|
||||||
* @return 对象
|
* @return 对象
|
||||||
* @see BeanPath#get(Object)
|
* @see BeanPathOld#get(Object)
|
||||||
* @since 5.7.14
|
* @since 5.7.14
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T getByPath(final String expression) {
|
public <T> T getByPath(final String expression) {
|
||||||
return (T) BeanPath.of(expression).get(this);
|
return (T) BeanPathOld.of(expression).get(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -453,7 +453,7 @@ public class Dict extends CustomKeyMap<String, Object> implements TypeGetter<Str
|
|||||||
* @param expression 表达式
|
* @param expression 表达式
|
||||||
* @param resultType 返回值类型
|
* @param resultType 返回值类型
|
||||||
* @return 对象
|
* @return 对象
|
||||||
* @see BeanPath#get(Object)
|
* @see BeanPathOld#get(Object)
|
||||||
* @since 5.7.14
|
* @since 5.7.14
|
||||||
*/
|
*/
|
||||||
public <T> T getByPath(final String expression, final Type resultType) {
|
public <T> T getByPath(final String expression, final Type resultType) {
|
||||||
|
@ -69,7 +69,7 @@ public abstract class StrTemplate {
|
|||||||
* @param template 字符串模板
|
* @param template 字符串模板
|
||||||
* @return 单占位符 模板对象的 Builder
|
* @return 单占位符 模板对象的 Builder
|
||||||
*/
|
*/
|
||||||
public static SinglePlaceholderStrTemplate.Builder of(String template) {
|
public static SinglePlaceholderStrTemplate.Builder of(final String template) {
|
||||||
return SinglePlaceholderStrTemplate.builder(template);
|
return SinglePlaceholderStrTemplate.builder(template);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ public abstract class StrTemplate {
|
|||||||
* @param template 字符串模板
|
* @param template 字符串模板
|
||||||
* @return 有前缀和后缀的占位符模板对象的 Builder
|
* @return 有前缀和后缀的占位符模板对象的 Builder
|
||||||
*/
|
*/
|
||||||
public static NamedPlaceholderStrTemplate.Builder ofNamed(String template) {
|
public static NamedPlaceholderStrTemplate.Builder ofNamed(final String template) {
|
||||||
return NamedPlaceholderStrTemplate.builder(template);
|
return NamedPlaceholderStrTemplate.builder(template);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ public abstract class StrTemplate {
|
|||||||
int startIdx = 0, findIdx;
|
int startIdx = 0, findIdx;
|
||||||
boolean hasPlaceholder = false;
|
boolean hasPlaceholder = false;
|
||||||
String text;
|
String text;
|
||||||
for (StrTemplateSegment segment : segments) {
|
for (final StrTemplateSegment segment : segments) {
|
||||||
if (segment instanceof LiteralSegment) {
|
if (segment instanceof LiteralSegment) {
|
||||||
text = segment.getText();
|
text = segment.getText();
|
||||||
findIdx = str.indexOf(text, startIdx);
|
findIdx = str.indexOf(text, startIdx);
|
||||||
@ -274,7 +274,7 @@ public abstract class StrTemplate {
|
|||||||
int totalTextLength = this.fixedTextTotalLength;
|
int totalTextLength = this.fixedTextTotalLength;
|
||||||
|
|
||||||
String valueStr;
|
String valueStr;
|
||||||
for (AbstractPlaceholderSegment segment : placeholderSegments) {
|
for (final AbstractPlaceholderSegment segment : placeholderSegments) {
|
||||||
// 根据 占位符 返回 需要序列化的值
|
// 根据 占位符 返回 需要序列化的值
|
||||||
valueStr = valueSupplier.apply(segment);
|
valueStr = valueSupplier.apply(segment);
|
||||||
if (valueStr == null) {
|
if (valueStr == null) {
|
||||||
@ -287,7 +287,7 @@ public abstract class StrTemplate {
|
|||||||
final StringBuilder sb = new StringBuilder(totalTextLength);
|
final StringBuilder sb = new StringBuilder(totalTextLength);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
// 构造格式化结果字符串
|
// 构造格式化结果字符串
|
||||||
for (StrTemplateSegment segment : segments) {
|
for (final StrTemplateSegment segment : segments) {
|
||||||
if (segment instanceof LiteralSegment) {
|
if (segment instanceof LiteralSegment) {
|
||||||
sb.append(segment.getText());
|
sb.append(segment.getText());
|
||||||
}
|
}
|
||||||
@ -331,7 +331,7 @@ public abstract class StrTemplate {
|
|||||||
protected String formatBySegment(final Function<AbstractPlaceholderSegment, ?> valueSupplier) {
|
protected String formatBySegment(final Function<AbstractPlaceholderSegment, ?> valueSupplier) {
|
||||||
return formatRawBySegment(segment -> {
|
return formatRawBySegment(segment -> {
|
||||||
// 根据 占位符 返回 需要序列化的值
|
// 根据 占位符 返回 需要序列化的值
|
||||||
Object value = valueSupplier.apply(segment);
|
final Object value = valueSupplier.apply(segment);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
if (value instanceof String) {
|
if (value instanceof String) {
|
||||||
return (String) value;
|
return (String) value;
|
||||||
@ -428,7 +428,7 @@ public abstract class StrTemplate {
|
|||||||
int startIdx = 0, findIdx;
|
int startIdx = 0, findIdx;
|
||||||
AbstractPlaceholderSegment placeholderSegment = null;
|
AbstractPlaceholderSegment placeholderSegment = null;
|
||||||
String text;
|
String text;
|
||||||
for (StrTemplateSegment segment : segments) {
|
for (final StrTemplateSegment segment : segments) {
|
||||||
if (segment instanceof LiteralSegment) {
|
if (segment instanceof LiteralSegment) {
|
||||||
text = segment.getText();
|
text = segment.getText();
|
||||||
// 查找固定文本
|
// 查找固定文本
|
||||||
@ -616,7 +616,7 @@ public abstract class StrTemplate {
|
|||||||
|
|
||||||
// 计算 固定文本segment 的 数量 和 文本总长度
|
// 计算 固定文本segment 的 数量 和 文本总长度
|
||||||
int literalSegmentSize = 0, fixedTextTotalLength = 0;
|
int literalSegmentSize = 0, fixedTextTotalLength = 0;
|
||||||
for (StrTemplateSegment segment : this.segments) {
|
for (final StrTemplateSegment segment : this.segments) {
|
||||||
if (segment instanceof LiteralSegment) {
|
if (segment instanceof LiteralSegment) {
|
||||||
++literalSegmentSize;
|
++literalSegmentSize;
|
||||||
fixedTextTotalLength += segment.getText().length();
|
fixedTextTotalLength += segment.getText().length();
|
||||||
@ -630,7 +630,7 @@ public abstract class StrTemplate {
|
|||||||
this.placeholderSegments = Collections.emptyList();
|
this.placeholderSegments = Collections.emptyList();
|
||||||
} else {
|
} else {
|
||||||
final List<AbstractPlaceholderSegment> placeholderSegments = new ArrayList<>(placeholderSegmentsSize);
|
final List<AbstractPlaceholderSegment> placeholderSegments = new ArrayList<>(placeholderSegmentsSize);
|
||||||
for (StrTemplateSegment segment : segments) {
|
for (final StrTemplateSegment segment : segments) {
|
||||||
if (segment instanceof AbstractPlaceholderSegment) {
|
if (segment instanceof AbstractPlaceholderSegment) {
|
||||||
placeholderSegments.add((AbstractPlaceholderSegment) segment);
|
placeholderSegments.add((AbstractPlaceholderSegment) segment);
|
||||||
}
|
}
|
||||||
@ -646,14 +646,14 @@ public abstract class StrTemplate {
|
|||||||
* @param list 已保存的segment列表
|
* @param list 已保存的segment列表
|
||||||
* @param newText 新的固定文本
|
* @param newText 新的固定文本
|
||||||
*/
|
*/
|
||||||
protected void addLiteralSegment(boolean isLastLiteralSegment, List<StrTemplateSegment> list, String newText) {
|
protected void addLiteralSegment(final boolean isLastLiteralSegment, final List<StrTemplateSegment> list, final String newText) {
|
||||||
if (newText.isEmpty()) {
|
if (newText.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isLastLiteralSegment) {
|
if (isLastLiteralSegment) {
|
||||||
// 最后的固定文本segment 和 新固定文本 合并为一个
|
// 最后的固定文本segment 和 新固定文本 合并为一个
|
||||||
int lastIdx = list.size() - 1;
|
final int lastIdx = list.size() - 1;
|
||||||
StrTemplateSegment lastLiteralSegment = list.get(lastIdx);
|
final StrTemplateSegment lastLiteralSegment = list.get(lastIdx);
|
||||||
list.set(lastIdx, new LiteralSegment(lastLiteralSegment.getText() + newText));
|
list.set(lastIdx, new LiteralSegment(lastLiteralSegment.getText() + newText));
|
||||||
} else {
|
} else {
|
||||||
list.add(new LiteralSegment(newText));
|
list.add(new LiteralSegment(newText));
|
||||||
@ -756,7 +756,7 @@ public abstract class StrTemplate {
|
|||||||
*/
|
*/
|
||||||
public BuilderChild addFeatures(final Feature... appendFeatures) {
|
public BuilderChild addFeatures(final Feature... appendFeatures) {
|
||||||
if (ArrayUtil.isNotEmpty(appendFeatures)) {
|
if (ArrayUtil.isNotEmpty(appendFeatures)) {
|
||||||
for (Feature feature : appendFeatures) {
|
for (final Feature feature : appendFeatures) {
|
||||||
this.features = feature.set(this.features);
|
this.features = feature.set(this.features);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -772,7 +772,7 @@ public abstract class StrTemplate {
|
|||||||
*/
|
*/
|
||||||
public BuilderChild removeFeatures(final Feature... removeFeatures) {
|
public BuilderChild removeFeatures(final Feature... removeFeatures) {
|
||||||
if (ArrayUtil.isNotEmpty(removeFeatures)) {
|
if (ArrayUtil.isNotEmpty(removeFeatures)) {
|
||||||
for (Feature feature : removeFeatures) {
|
for (final Feature feature : removeFeatures) {
|
||||||
this.features = feature.clear(this.features);
|
this.features = feature.clear(this.features);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -978,7 +978,7 @@ public abstract class StrTemplate {
|
|||||||
* @param bitStart 同组第一个策略的掩码位数
|
* @param bitStart 同组第一个策略的掩码位数
|
||||||
* @param bitLen 同组策略数量
|
* @param bitLen 同组策略数量
|
||||||
*/
|
*/
|
||||||
Feature(int bitPos, int bitStart, int bitLen) {
|
Feature(final int bitPos, final int bitStart, final int bitLen) {
|
||||||
this.mask = 1 << bitPos;
|
this.mask = 1 << bitPos;
|
||||||
this.clearMask = (-1 << (bitStart + bitLen)) | ((1 << bitStart) - 1);
|
this.clearMask = (-1 << (bitStart + bitLen)) | ((1 << bitStart) - 1);
|
||||||
}
|
}
|
||||||
@ -989,7 +989,7 @@ public abstract class StrTemplate {
|
|||||||
* @param features 外部的策略值
|
* @param features 外部的策略值
|
||||||
* @return 是否为当前策略
|
* @return 是否为当前策略
|
||||||
*/
|
*/
|
||||||
public boolean contains(int features) {
|
public boolean contains(final int features) {
|
||||||
return (features & mask) != 0;
|
return (features & mask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -999,7 +999,7 @@ public abstract class StrTemplate {
|
|||||||
* @param features 外部的策略值
|
* @param features 外部的策略值
|
||||||
* @return 添加后的策略值
|
* @return 添加后的策略值
|
||||||
*/
|
*/
|
||||||
public int set(int features) {
|
public int set(final int features) {
|
||||||
return (features & clearMask) | mask;
|
return (features & clearMask) | mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1009,7 +1009,7 @@ public abstract class StrTemplate {
|
|||||||
* @param features 外部的策略值
|
* @param features 外部的策略值
|
||||||
* @return 移除后的策略值
|
* @return 移除后的策略值
|
||||||
*/
|
*/
|
||||||
public int clear(int features) {
|
public int clear(final int features) {
|
||||||
return (features & clearMask);
|
return (features & clearMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1019,13 +1019,13 @@ public abstract class StrTemplate {
|
|||||||
* @param features 策略枚举数组
|
* @param features 策略枚举数组
|
||||||
* @return 总的策略值
|
* @return 总的策略值
|
||||||
*/
|
*/
|
||||||
public static int of(Feature... features) {
|
public static int of(final Feature... features) {
|
||||||
if (features == null) {
|
if (features == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int value = 0;
|
int value = 0;
|
||||||
for (Feature feature : features) {
|
for (final Feature feature : features) {
|
||||||
value = feature.set(value);
|
value = feature.set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 占位符节点
|
||||||
|
*/
|
||||||
|
package org.dromara.hutool.core.text.placeholder.segment;
|
@ -76,7 +76,7 @@ public class NamedPlaceholderStrTemplate extends StrTemplate {
|
|||||||
|
|
||||||
// 记录 下标占位符 最大的 下标值
|
// 记录 下标占位符 最大的 下标值
|
||||||
if (!placeholderSegments.isEmpty()) {
|
if (!placeholderSegments.isEmpty()) {
|
||||||
for (AbstractPlaceholderSegment segment : placeholderSegments) {
|
for (final AbstractPlaceholderSegment segment : placeholderSegments) {
|
||||||
if (segment instanceof IndexedPlaceholderSegment) {
|
if (segment instanceof IndexedPlaceholderSegment) {
|
||||||
this.indexedSegmentMaxIdx = Math.max(this.indexedSegmentMaxIdx, ((IndexedPlaceholderSegment) segment).getIndex());
|
this.indexedSegmentMaxIdx = Math.max(this.indexedSegmentMaxIdx, ((IndexedPlaceholderSegment) segment).getIndex());
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ public class NamedPlaceholderStrTemplate extends StrTemplate {
|
|||||||
|
|
||||||
final int openLength = prefix.length();
|
final int openLength = prefix.length();
|
||||||
final int closeLength = suffix.length();
|
final int closeLength = suffix.length();
|
||||||
List<StrTemplateSegment> segments = new ArrayList<>();
|
final List<StrTemplateSegment> segments = new ArrayList<>();
|
||||||
int closeCursor = 0;
|
int closeCursor = 0;
|
||||||
// 开始匹配
|
// 开始匹配
|
||||||
final char[] src = template.toCharArray();
|
final char[] src = template.toCharArray();
|
||||||
@ -299,7 +299,7 @@ public class NamedPlaceholderStrTemplate extends StrTemplate {
|
|||||||
* @param missingIndexHandler 集合中不存在下标位置时的处理器,根据 下标 返回 代替值
|
* @param missingIndexHandler 集合中不存在下标位置时的处理器,根据 下标 返回 代替值
|
||||||
* @return 格式化字符串
|
* @return 格式化字符串
|
||||||
*/
|
*/
|
||||||
public String formatIndexed(final Collection<?> collection, IntFunction<String> missingIndexHandler) {
|
public String formatIndexed(final Collection<?> collection, final IntFunction<String> missingIndexHandler) {
|
||||||
if (collection == null) {
|
if (collection == null) {
|
||||||
return getTemplate();
|
return getTemplate();
|
||||||
}
|
}
|
||||||
@ -579,6 +579,9 @@ public class NamedPlaceholderStrTemplate extends StrTemplate {
|
|||||||
return new Builder(template);
|
return new Builder(template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造器
|
||||||
|
*/
|
||||||
public static class Builder extends AbstractBuilder<Builder, NamedPlaceholderStrTemplate> {
|
public static class Builder extends AbstractBuilder<Builder, NamedPlaceholderStrTemplate> {
|
||||||
/**
|
/**
|
||||||
* 占位符前缀,默认为 {@link NamedPlaceholderStrTemplate#DEFAULT_PREFIX}
|
* 占位符前缀,默认为 {@link NamedPlaceholderStrTemplate#DEFAULT_PREFIX}
|
||||||
|
@ -34,196 +34,199 @@ import java.util.function.UnaryOperator;
|
|||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class SinglePlaceholderStrTemplate extends StrTemplate {
|
public class SinglePlaceholderStrTemplate extends StrTemplate {
|
||||||
/**
|
/**
|
||||||
* 默认的占位符
|
* 默认的占位符
|
||||||
*/
|
*/
|
||||||
public static final String DEFAULT_PLACEHOLDER = StrPool.EMPTY_JSON;
|
public static final String DEFAULT_PLACEHOLDER = StrPool.EMPTY_JSON;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 占位符,默认为: {@link StrPool#EMPTY_JSON}
|
* 占位符,默认为: {@link StrPool#EMPTY_JSON}
|
||||||
*/
|
*/
|
||||||
protected String placeholder;
|
protected String placeholder;
|
||||||
|
|
||||||
protected SinglePlaceholderStrTemplate(final String template, final int features, final String placeholder, final char escape,
|
protected SinglePlaceholderStrTemplate(final String template, final int features, final String placeholder, final char escape,
|
||||||
final String defaultValue, final UnaryOperator<String> defaultValueHandler) {
|
final String defaultValue, final UnaryOperator<String> defaultValueHandler) {
|
||||||
super(template, escape, defaultValue, defaultValueHandler, features);
|
super(template, escape, defaultValue, defaultValueHandler, features);
|
||||||
|
|
||||||
Assert.notEmpty(placeholder);
|
Assert.notEmpty(placeholder);
|
||||||
this.placeholder = placeholder;
|
this.placeholder = placeholder;
|
||||||
|
|
||||||
// 初始化Segment列表
|
// 初始化Segment列表
|
||||||
afterInit();
|
afterInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<StrTemplateSegment> parseSegments(final String template) {
|
protected List<StrTemplateSegment> parseSegments(final String template) {
|
||||||
final int placeholderLength = placeholder.length();
|
final int placeholderLength = placeholder.length();
|
||||||
final int strPatternLength = template.length();
|
final int strPatternLength = template.length();
|
||||||
// 记录已经处理到的位置
|
// 记录已经处理到的位置
|
||||||
int handledPosition = 0;
|
int handledPosition = 0;
|
||||||
// 占位符所在位置
|
// 占位符所在位置
|
||||||
int delimIndex;
|
int delimIndex;
|
||||||
// 上一个解析的segment是否是固定文本,如果是,则需要和当前新的文本部分合并
|
// 上一个解析的segment是否是固定文本,如果是,则需要和当前新的文本部分合并
|
||||||
boolean lastIsLiteralSegment = false;
|
boolean lastIsLiteralSegment = false;
|
||||||
// 复用的占位符变量
|
// 复用的占位符变量
|
||||||
final SinglePlaceholderSegment singlePlaceholderSegment = SinglePlaceholderSegment.newInstance(placeholder);
|
final SinglePlaceholderSegment singlePlaceholderSegment = SinglePlaceholderSegment.newInstance(placeholder);
|
||||||
List<StrTemplateSegment> segments = null;
|
List<StrTemplateSegment> segments = null;
|
||||||
while (true) {
|
while (true) {
|
||||||
delimIndex = template.indexOf(placeholder, handledPosition);
|
delimIndex = template.indexOf(placeholder, handledPosition);
|
||||||
if (delimIndex == -1) {
|
if (delimIndex == -1) {
|
||||||
// 整个模板都不带占位符
|
// 整个模板都不带占位符
|
||||||
if (handledPosition == 0) {
|
if (handledPosition == 0) {
|
||||||
return Collections.singletonList(new LiteralSegment(template));
|
return Collections.singletonList(new LiteralSegment(template));
|
||||||
}
|
}
|
||||||
// 字符串模板剩余部分不再包含占位符
|
// 字符串模板剩余部分不再包含占位符
|
||||||
if (handledPosition < strPatternLength) {
|
if (handledPosition < strPatternLength) {
|
||||||
addLiteralSegment(lastIsLiteralSegment, segments, template.substring(handledPosition));
|
addLiteralSegment(lastIsLiteralSegment, segments, template.substring(handledPosition));
|
||||||
}
|
}
|
||||||
return segments;
|
return segments;
|
||||||
} else if (segments == null) {
|
} else if (segments == null) {
|
||||||
segments = new ArrayList<>();
|
segments = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 存在 转义符
|
// 存在 转义符
|
||||||
if (delimIndex > 0 && template.charAt(delimIndex - 1) == escape) {
|
if (delimIndex > 0 && template.charAt(delimIndex - 1) == escape) {
|
||||||
// 存在 双转义符
|
// 存在 双转义符
|
||||||
if (delimIndex > 1 && template.charAt(delimIndex - 2) == escape) {
|
if (delimIndex > 1 && template.charAt(delimIndex - 2) == escape) {
|
||||||
// 转义符之前还有一个转义符,形如:"//{",占位符依旧有效
|
// 转义符之前还有一个转义符,形如:"//{",占位符依旧有效
|
||||||
addLiteralSegment(lastIsLiteralSegment, segments, template.substring(handledPosition, delimIndex - 1));
|
addLiteralSegment(lastIsLiteralSegment, segments, template.substring(handledPosition, delimIndex - 1));
|
||||||
segments.add(singlePlaceholderSegment);
|
segments.add(singlePlaceholderSegment);
|
||||||
lastIsLiteralSegment = false;
|
lastIsLiteralSegment = false;
|
||||||
handledPosition = delimIndex + placeholderLength;
|
handledPosition = delimIndex + placeholderLength;
|
||||||
} else {
|
} else {
|
||||||
// 占位符被转义,形如:"/{",当前字符并不是一个真正的占位符,而是普通字符串的一部分
|
// 占位符被转义,形如:"/{",当前字符并不是一个真正的占位符,而是普通字符串的一部分
|
||||||
addLiteralSegment(lastIsLiteralSegment, segments, template.substring(handledPosition, delimIndex - 1) + placeholder.charAt(0));
|
addLiteralSegment(lastIsLiteralSegment, segments, template.substring(handledPosition, delimIndex - 1) + placeholder.charAt(0));
|
||||||
lastIsLiteralSegment = true;
|
lastIsLiteralSegment = true;
|
||||||
handledPosition = delimIndex + 1;
|
handledPosition = delimIndex + 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 正常占位符
|
// 正常占位符
|
||||||
addLiteralSegment(lastIsLiteralSegment, segments, template.substring(handledPosition, delimIndex));
|
addLiteralSegment(lastIsLiteralSegment, segments, template.substring(handledPosition, delimIndex));
|
||||||
segments.add(singlePlaceholderSegment);
|
segments.add(singlePlaceholderSegment);
|
||||||
lastIsLiteralSegment = false;
|
lastIsLiteralSegment = false;
|
||||||
handledPosition = delimIndex + placeholderLength;
|
handledPosition = delimIndex + placeholderLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// region 格式化方法
|
// region 格式化方法
|
||||||
// ################################################## 格式化方法 ##################################################
|
// ################################################## 格式化方法 ##################################################
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按顺序使用 数组元素 替换 占位符
|
* 按顺序使用 数组元素 替换 占位符
|
||||||
*
|
*
|
||||||
* @param args 可变参数
|
* @param args 可变参数
|
||||||
* @return 格式化字符串
|
* @return 格式化字符串
|
||||||
*/
|
*/
|
||||||
public String format(final Object... args) {
|
public String format(final Object... args) {
|
||||||
return formatArray(args);
|
return formatArray(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按顺序使用 原始数组元素 替换 占位符
|
* 按顺序使用 原始数组元素 替换 占位符
|
||||||
*
|
*
|
||||||
* @param array 原始类型数组,例如: {@code int[]}
|
* @param array 原始类型数组,例如: {@code int[]}
|
||||||
* @return 格式化字符串
|
* @return 格式化字符串
|
||||||
*/
|
*/
|
||||||
public String formatArray(final Object array) {
|
public String formatArray(final Object array) {
|
||||||
return formatArray(ArrayUtil.wrap(array));
|
return formatArray(ArrayUtil.wrap(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按顺序使用 数组元素 替换 占位符
|
* 按顺序使用 数组元素 替换 占位符
|
||||||
*
|
*
|
||||||
* @param array 数组
|
* @param array 数组
|
||||||
* @return 格式化字符串
|
* @return 格式化字符串
|
||||||
*/
|
*/
|
||||||
public String formatArray(final Object[] array) {
|
public String formatArray(final Object[] array) {
|
||||||
if (array == null) {
|
if (array == null) {
|
||||||
return getTemplate();
|
return getTemplate();
|
||||||
}
|
}
|
||||||
return format(Arrays.asList(array));
|
return format(Arrays.asList(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按顺序使用 迭代器元素 替换 占位符
|
* 按顺序使用 迭代器元素 替换 占位符
|
||||||
*
|
*
|
||||||
* @param iterable iterable
|
* @param iterable iterable
|
||||||
* @return 格式化字符串
|
* @return 格式化字符串
|
||||||
*/
|
*/
|
||||||
public String format(final Iterable<?> iterable) {
|
public String format(final Iterable<?> iterable) {
|
||||||
return super.formatSequence(iterable);
|
return super.formatSequence(iterable);
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region 解析方法
|
// region 解析方法
|
||||||
// ################################################## 解析方法 ##################################################
|
// ################################################## 解析方法 ##################################################
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 占位符位置的值 按顺序解析为 字符串数组
|
* 将 占位符位置的值 按顺序解析为 字符串数组
|
||||||
*
|
*
|
||||||
* @param str 待解析的字符串,一般是格式化方法的返回值
|
* @param str 待解析的字符串,一般是格式化方法的返回值
|
||||||
* @return 参数值数组
|
* @return 参数值数组
|
||||||
*/
|
*/
|
||||||
public String[] matchesToArray(final String str) {
|
public String[] matchesToArray(final String str) {
|
||||||
return matches(str).toArray(new String[0]);
|
return matches(str).toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 占位符位置的值 按顺序解析为 字符串列表
|
* 将 占位符位置的值 按顺序解析为 字符串列表
|
||||||
*
|
*
|
||||||
* @param str 待解析的字符串,一般是格式化方法的返回值
|
* @param str 待解析的字符串,一般是格式化方法的返回值
|
||||||
* @return 参数值列表
|
* @return 参数值列表
|
||||||
*/
|
*/
|
||||||
public List<String> matches(final String str) {
|
public List<String> matches(final String str) {
|
||||||
return super.matchesSequence(str);
|
return super.matchesSequence(str);
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建 builder
|
* 创建 builder
|
||||||
*
|
*
|
||||||
* @param template 字符串模板,不能为 {@code null}
|
* @param template 字符串模板,不能为 {@code null}
|
||||||
* @return builder实例
|
* @return builder实例
|
||||||
*/
|
*/
|
||||||
public static Builder builder(final String template) {
|
public static Builder builder(final String template) {
|
||||||
return new Builder(template);
|
return new Builder(template);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends AbstractBuilder<Builder, SinglePlaceholderStrTemplate> {
|
/**
|
||||||
/**
|
* 构造器
|
||||||
* 单占位符
|
*/
|
||||||
* <p>例如:"?"、"{}"</p>
|
public static class Builder extends AbstractBuilder<Builder, SinglePlaceholderStrTemplate> {
|
||||||
* <p>默认为 {@link SinglePlaceholderStrTemplate#DEFAULT_PLACEHOLDER}</p>
|
/**
|
||||||
*/
|
* 单占位符
|
||||||
protected String placeholder;
|
* <p>例如:"?"、"{}"</p>
|
||||||
|
* <p>默认为 {@link SinglePlaceholderStrTemplate#DEFAULT_PLACEHOLDER}</p>
|
||||||
|
*/
|
||||||
|
protected String placeholder;
|
||||||
|
|
||||||
protected Builder(final String template) {
|
protected Builder(final String template) {
|
||||||
super(template);
|
super(template);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置 占位符
|
* 设置 占位符
|
||||||
*
|
*
|
||||||
* @param placeholder 占位符,不能为 {@code null} 和 {@code ""}
|
* @param placeholder 占位符,不能为 {@code null} 和 {@code ""}
|
||||||
* @return builder
|
* @return builder
|
||||||
*/
|
*/
|
||||||
public Builder placeholder(final String placeholder) {
|
public Builder placeholder(final String placeholder) {
|
||||||
this.placeholder = placeholder;
|
this.placeholder = placeholder;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SinglePlaceholderStrTemplate buildInstance() {
|
protected SinglePlaceholderStrTemplate buildInstance() {
|
||||||
if (this.placeholder == null) {
|
if (this.placeholder == null) {
|
||||||
this.placeholder = DEFAULT_PLACEHOLDER;
|
this.placeholder = DEFAULT_PLACEHOLDER;
|
||||||
}
|
}
|
||||||
return new SinglePlaceholderStrTemplate(this.template, this.features, this.placeholder, this.escape,
|
return new SinglePlaceholderStrTemplate(this.template, this.features, this.placeholder, this.escape,
|
||||||
this.defaultValue, this.defaultValueHandler);
|
this.defaultValue, this.defaultValueHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Builder self() {
|
protected Builder self() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串模板
|
||||||
|
*/
|
||||||
|
package org.dromara.hutool.core.text.placeholder.template;
|
@ -27,7 +27,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link BeanPath} 单元测试
|
* {@link BeanPathOld} 单元测试
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
*
|
*
|
||||||
@ -73,7 +73,7 @@ public class BeanPathTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void beanPathTest1() {
|
public void beanPathTest1() {
|
||||||
final BeanPath pattern = new BeanPath("userInfo.examInfoDict[0].id");
|
final BeanPathOld pattern = new BeanPathOld("userInfo.examInfoDict[0].id");
|
||||||
Assertions.assertEquals("userInfo", pattern.patternParts.get(0));
|
Assertions.assertEquals("userInfo", pattern.patternParts.get(0));
|
||||||
Assertions.assertEquals("examInfoDict", pattern.patternParts.get(1));
|
Assertions.assertEquals("examInfoDict", pattern.patternParts.get(1));
|
||||||
Assertions.assertEquals("0", pattern.patternParts.get(2));
|
Assertions.assertEquals("0", pattern.patternParts.get(2));
|
||||||
@ -83,7 +83,7 @@ public class BeanPathTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void beanPathTest2() {
|
public void beanPathTest2() {
|
||||||
final BeanPath pattern = new BeanPath("[userInfo][examInfoDict][0][id]");
|
final BeanPathOld pattern = new BeanPathOld("[userInfo][examInfoDict][0][id]");
|
||||||
Assertions.assertEquals("userInfo", pattern.patternParts.get(0));
|
Assertions.assertEquals("userInfo", pattern.patternParts.get(0));
|
||||||
Assertions.assertEquals("examInfoDict", pattern.patternParts.get(1));
|
Assertions.assertEquals("examInfoDict", pattern.patternParts.get(1));
|
||||||
Assertions.assertEquals("0", pattern.patternParts.get(2));
|
Assertions.assertEquals("0", pattern.patternParts.get(2));
|
||||||
@ -92,7 +92,7 @@ public class BeanPathTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void beanPathTest3() {
|
public void beanPathTest3() {
|
||||||
final BeanPath pattern = new BeanPath("['userInfo']['examInfoDict'][0]['id']");
|
final BeanPathOld pattern = new BeanPathOld("['userInfo']['examInfoDict'][0]['id']");
|
||||||
Assertions.assertEquals("userInfo", pattern.patternParts.get(0));
|
Assertions.assertEquals("userInfo", pattern.patternParts.get(0));
|
||||||
Assertions.assertEquals("examInfoDict", pattern.patternParts.get(1));
|
Assertions.assertEquals("examInfoDict", pattern.patternParts.get(1));
|
||||||
Assertions.assertEquals("0", pattern.patternParts.get(2));
|
Assertions.assertEquals("0", pattern.patternParts.get(2));
|
||||||
@ -101,14 +101,14 @@ public class BeanPathTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getTest() {
|
public void getTest() {
|
||||||
final BeanPath pattern = BeanPath.of("userInfo.examInfoDict[0].id");
|
final BeanPathOld pattern = BeanPathOld.of("userInfo.examInfoDict[0].id");
|
||||||
final Object result = pattern.get(tempMap);
|
final Object result = pattern.get(tempMap);
|
||||||
Assertions.assertEquals(1, result);
|
Assertions.assertEquals(1, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setTest() {
|
public void setTest() {
|
||||||
final BeanPath pattern = BeanPath.of("userInfo.examInfoDict[0].id");
|
final BeanPathOld pattern = BeanPathOld.of("userInfo.examInfoDict[0].id");
|
||||||
pattern.set(tempMap, 2);
|
pattern.set(tempMap, 2);
|
||||||
final Object result = pattern.get(tempMap);
|
final Object result = pattern.get(tempMap);
|
||||||
Assertions.assertEquals(2, result);
|
Assertions.assertEquals(2, result);
|
||||||
@ -116,7 +116,7 @@ public class BeanPathTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getMapTest () {
|
public void getMapTest () {
|
||||||
final BeanPath pattern = BeanPath.of("userInfo[id, photoPath]");
|
final BeanPathOld pattern = BeanPathOld.of("userInfo[id, photoPath]");
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Map<String, Object> result = (Map<String, Object>)pattern.get(tempMap);
|
final Map<String, Object> result = (Map<String, Object>)pattern.get(tempMap);
|
||||||
Assertions.assertEquals(1, result.get("id"));
|
Assertions.assertEquals(1, result.get("id"));
|
||||||
@ -129,13 +129,13 @@ public class BeanPathTest {
|
|||||||
dataMap.put("aa", "value0");
|
dataMap.put("aa", "value0");
|
||||||
dataMap.put("aa.bb.cc", "value111111");// key 是类名 格式 带 ' . '
|
dataMap.put("aa.bb.cc", "value111111");// key 是类名 格式 带 ' . '
|
||||||
|
|
||||||
final BeanPath pattern = BeanPath.of("'aa.bb.cc'");
|
final BeanPathOld pattern = BeanPathOld.of("'aa.bb.cc'");
|
||||||
Assertions.assertEquals("value111111", pattern.get(dataMap));
|
Assertions.assertEquals("value111111", pattern.get(dataMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void compileTest(){
|
public void compileTest(){
|
||||||
final BeanPath of = BeanPath.of("'abc.dd'.ee.ff'.'");
|
final BeanPathOld of = BeanPathOld.of("'abc.dd'.ee.ff'.'");
|
||||||
Assertions.assertEquals("abc.dd", of.getPatternParts().get(0));
|
Assertions.assertEquals("abc.dd", of.getPatternParts().get(0));
|
||||||
Assertions.assertEquals("ee", of.getPatternParts().get(1));
|
Assertions.assertEquals("ee", of.getPatternParts().get(1));
|
||||||
Assertions.assertEquals("ff.", of.getPatternParts().get(2));
|
Assertions.assertEquals("ff.", of.getPatternParts().get(2));
|
||||||
@ -145,17 +145,17 @@ public class BeanPathTest {
|
|||||||
public void issue2362Test() {
|
public void issue2362Test() {
|
||||||
final Map<String, Object> map = new HashMap<>();
|
final Map<String, Object> map = new HashMap<>();
|
||||||
|
|
||||||
BeanPath beanPath = BeanPath.of("list[0].name");
|
BeanPathOld beanPath = BeanPathOld.of("list[0].name");
|
||||||
beanPath.set(map, "张三");
|
beanPath.set(map, "张三");
|
||||||
Assertions.assertEquals("{list=[{name=张三}]}", map.toString());
|
Assertions.assertEquals("{list=[{name=张三}]}", map.toString());
|
||||||
|
|
||||||
map.clear();
|
map.clear();
|
||||||
beanPath = BeanPath.of("list[1].name");
|
beanPath = BeanPathOld.of("list[1].name");
|
||||||
beanPath.set(map, "张三");
|
beanPath.set(map, "张三");
|
||||||
Assertions.assertEquals("{list=[null, {name=张三}]}", map.toString());
|
Assertions.assertEquals("{list=[null, {name=张三}]}", map.toString());
|
||||||
|
|
||||||
map.clear();
|
map.clear();
|
||||||
beanPath = BeanPath.of("list[0].1.name");
|
beanPath = BeanPathOld.of("list[0].1.name");
|
||||||
beanPath.set(map, "张三");
|
beanPath.set(map, "张三");
|
||||||
Assertions.assertEquals("{list=[[null, {name=张三}]]}", map.toString());
|
Assertions.assertEquals("{list=[[null, {name=张三}]]}", map.toString());
|
||||||
}
|
}
|
||||||
@ -164,7 +164,7 @@ public class BeanPathTest {
|
|||||||
public void putTest() {
|
public void putTest() {
|
||||||
final Map<String, Object> map = new HashMap<>();
|
final Map<String, Object> map = new HashMap<>();
|
||||||
|
|
||||||
BeanPath beanPath = BeanPath.of("list[1].name");
|
final BeanPathOld beanPath = BeanPathOld.of("list[1].name");
|
||||||
beanPath.set(map, "张三");
|
beanPath.set(map, "张三");
|
||||||
Assertions.assertEquals("{list=[null, {name=张三}]}", map.toString());
|
Assertions.assertEquals("{list=[null, {name=张三}]}", map.toString());
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ public class BeanPathTest {
|
|||||||
@Test
|
@Test
|
||||||
public void putByPathTest() {
|
public void putByPathTest() {
|
||||||
final Dict dict = new Dict();
|
final Dict dict = new Dict();
|
||||||
BeanPath.of("aa.bb").set(dict, "BB");
|
BeanPathOld.of("aa.bb").set(dict, "BB");
|
||||||
Assertions.assertEquals("{aa={bb=BB}}", dict.toString());
|
Assertions.assertEquals("{aa={bb=BB}}", dict.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,9 +180,9 @@ public class BeanPathTest {
|
|||||||
public void appendArrayTest(){
|
public void appendArrayTest(){
|
||||||
// issue#3008@Github
|
// issue#3008@Github
|
||||||
final MyUser myUser = new MyUser();
|
final MyUser myUser = new MyUser();
|
||||||
BeanPath.of("hobby[0]").set(myUser, "LOL");
|
BeanPathOld.of("hobby[0]").set(myUser, "LOL");
|
||||||
BeanPath.of("hobby[1]").set(myUser, "KFC");
|
BeanPathOld.of("hobby[1]").set(myUser, "KFC");
|
||||||
BeanPath.of("hobby[2]").set(myUser, "COFFE");
|
BeanPathOld.of("hobby[2]").set(myUser, "COFFE");
|
||||||
|
|
||||||
Assertions.assertEquals("[LOL, KFC, COFFE]", ArrayUtil.toString(myUser.getHobby()));
|
Assertions.assertEquals("[LOL, KFC, COFFE]", ArrayUtil.toString(myUser.getHobby()));
|
||||||
}
|
}
|
||||||
@ -191,9 +191,9 @@ public class BeanPathTest {
|
|||||||
public void appendArrayTest2(){
|
public void appendArrayTest2(){
|
||||||
// issue#3008@Github
|
// issue#3008@Github
|
||||||
final MyUser2 myUser = new MyUser2();
|
final MyUser2 myUser = new MyUser2();
|
||||||
BeanPath.of("myUser.hobby[0]").set(myUser, "LOL");
|
BeanPathOld.of("myUser.hobby[0]").set(myUser, "LOL");
|
||||||
BeanPath.of("myUser.hobby[1]").set(myUser, "KFC");
|
BeanPathOld.of("myUser.hobby[1]").set(myUser, "KFC");
|
||||||
BeanPath.of("myUser.hobby[2]").set(myUser, "COFFE");
|
BeanPathOld.of("myUser.hobby[2]").set(myUser, "COFFE");
|
||||||
|
|
||||||
Assertions.assertEquals("[LOL, KFC, COFFE]", ArrayUtil.toString(myUser.getMyUser().getHobby()));
|
Assertions.assertEquals("[LOL, KFC, COFFE]", ArrayUtil.toString(myUser.getMyUser().getHobby()));
|
||||||
}
|
}
|
||||||
|
@ -767,7 +767,7 @@ public class BeanUtilTest {
|
|||||||
|
|
||||||
testPojo.setTestPojo2List(new TestPojo2[]{testPojo2, testPojo3});
|
testPojo.setTestPojo2List(new TestPojo2[]{testPojo2, testPojo3});
|
||||||
|
|
||||||
final BeanPath beanPath = BeanPath.of("testPojo2List.age");
|
final BeanPathOld beanPath = BeanPathOld.of("testPojo2List.age");
|
||||||
final Object o = beanPath.get(testPojo);
|
final Object o = beanPath.get(testPojo);
|
||||||
|
|
||||||
Assertions.assertEquals(Integer.valueOf(2), ArrayUtil.get(o, 0));
|
Assertions.assertEquals(Integer.valueOf(2), ArrayUtil.get(o, 0));
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.core.bean.path;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.bean.BeanPathOld;
|
||||||
|
import org.dromara.hutool.core.lang.test.bean.ExamInfoDict;
|
||||||
|
import org.dromara.hutool.core.lang.test.bean.UserInfoDict;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class BeanPathGetOrSetValueTest {
|
||||||
|
Map<String, Object> tempMap;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void init() {
|
||||||
|
// ------------------------------------------------- 考试信息列表
|
||||||
|
final ExamInfoDict examInfoDict = new ExamInfoDict();
|
||||||
|
examInfoDict.setId(1);
|
||||||
|
examInfoDict.setExamType(0);
|
||||||
|
examInfoDict.setAnswerIs(1);
|
||||||
|
|
||||||
|
final ExamInfoDict examInfoDict1 = new ExamInfoDict();
|
||||||
|
examInfoDict1.setId(2);
|
||||||
|
examInfoDict1.setExamType(0);
|
||||||
|
examInfoDict1.setAnswerIs(0);
|
||||||
|
|
||||||
|
final ExamInfoDict examInfoDict2 = new ExamInfoDict();
|
||||||
|
examInfoDict2.setId(3);
|
||||||
|
examInfoDict2.setExamType(1);
|
||||||
|
examInfoDict2.setAnswerIs(0);
|
||||||
|
|
||||||
|
final List<ExamInfoDict> examInfoDicts = new ArrayList<>();
|
||||||
|
examInfoDicts.add(examInfoDict);
|
||||||
|
examInfoDicts.add(examInfoDict1);
|
||||||
|
examInfoDicts.add(examInfoDict2);
|
||||||
|
|
||||||
|
// ------------------------------------------------- 用户信息
|
||||||
|
final UserInfoDict userInfoDict = new UserInfoDict();
|
||||||
|
userInfoDict.setId(1);
|
||||||
|
userInfoDict.setPhotoPath("yx.mm.com");
|
||||||
|
userInfoDict.setRealName("张三");
|
||||||
|
userInfoDict.setExamInfoDict(examInfoDicts);
|
||||||
|
|
||||||
|
tempMap = new HashMap<>();
|
||||||
|
tempMap.put("userInfo", userInfoDict);
|
||||||
|
tempMap.put("flag", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getValueTest() {
|
||||||
|
final BeanPath pattern = new BeanPath("$.userInfo.examInfoDict[0].id");
|
||||||
|
final Object result = pattern.getValue(tempMap);
|
||||||
|
Assertions.assertEquals(1, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setValueTest() {
|
||||||
|
final BeanPath pattern = new BeanPath("userInfo.examInfoDict[0].id");
|
||||||
|
pattern.setValue(tempMap, 2);
|
||||||
|
final Object result = pattern.getValue(tempMap);
|
||||||
|
Assertions.assertEquals(2, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getMapTest () {
|
||||||
|
final BeanPath pattern = new BeanPath("userInfo[id, photoPath]");
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Map<String, Object> result = (Map<String, Object>)pattern.getValue(tempMap);
|
||||||
|
Assertions.assertEquals(1, result.get("id"));
|
||||||
|
Assertions.assertEquals("yx.mm.com", result.get("photoPath"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getKeyWithDotTest () {
|
||||||
|
final Map<String, Object> dataMap = new HashMap<>(16);
|
||||||
|
dataMap.put("aa", "value0");
|
||||||
|
dataMap.put("aa.bb.cc", "value111111");// key 是类名 格式 带 ' . '
|
||||||
|
|
||||||
|
final BeanPath pattern = new BeanPath("'aa.bb.cc'");
|
||||||
|
Assertions.assertEquals("value111111", pattern.getValue(dataMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void issue2362Test() {
|
||||||
|
final Map<String, Object> map = new HashMap<>();
|
||||||
|
|
||||||
|
BeanPath beanPath = BeanPath.of("list[0].name");
|
||||||
|
beanPath.setValue(map, "张三");
|
||||||
|
Assertions.assertEquals("{list=[{name=张三}]}", map.toString());
|
||||||
|
|
||||||
|
map.clear();
|
||||||
|
beanPath = BeanPath.of("list[1].name");
|
||||||
|
beanPath.setValue(map, "张三");
|
||||||
|
Assertions.assertEquals("{list=[null, {name=张三}]}", map.toString());
|
||||||
|
|
||||||
|
map.clear();
|
||||||
|
beanPath = BeanPath.of("list[0].1.name");
|
||||||
|
beanPath.setValue(map, "张三");
|
||||||
|
Assertions.assertEquals("{list=[[null, {name=张三}]]}", map.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.core.bean.path;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class BeanPathTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseDotTest() {
|
||||||
|
BeanPath beanPath = new BeanPath("userInfo.examInfoDict[0].id");
|
||||||
|
Assertions.assertEquals("userInfo", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("examInfoDict[0].id", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("examInfoDict", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[0].id", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("0", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals(".id", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("id", beanPath.getNode().toString());
|
||||||
|
Assertions.assertNull(beanPath.getChild());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseDotWithQuoteTest() {
|
||||||
|
BeanPath beanPath = new BeanPath("'userInfo'.examInfoDict[0].'id'");
|
||||||
|
Assertions.assertEquals("userInfo", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("examInfoDict[0].'id'", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("examInfoDict", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[0].'id'", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("0", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals(".'id'", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("id", beanPath.getNode().toString());
|
||||||
|
Assertions.assertNull(beanPath.getChild());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseDotWithQuoteTest2() {
|
||||||
|
BeanPath beanPath = new BeanPath("userInfo.'examInfoDict'[0].id");
|
||||||
|
Assertions.assertEquals("userInfo", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("'examInfoDict'[0].id", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("examInfoDict", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[0].id", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("0", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals(".id", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("id", beanPath.getNode().toString());
|
||||||
|
Assertions.assertNull(beanPath.getChild());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseBucketTest() {
|
||||||
|
BeanPath beanPath = new BeanPath("[userInfo][examInfoDict][0][id]");
|
||||||
|
Assertions.assertEquals("userInfo", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[examInfoDict][0][id]", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("examInfoDict", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[0][id]", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("0", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[id]", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("id", beanPath.getNode().toString());
|
||||||
|
Assertions.assertNull(beanPath.getChild());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseBucketWithQuoteTest() {
|
||||||
|
BeanPath beanPath = new BeanPath("['userInfo']['examInfoDict'][0][id]");
|
||||||
|
Assertions.assertEquals("userInfo", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("['examInfoDict'][0][id]", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("examInfoDict", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[0][id]", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("0", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[id]", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("id", beanPath.getNode().toString());
|
||||||
|
Assertions.assertNull(beanPath.getChild());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseBucketWithQuoteTest2() {
|
||||||
|
BeanPath beanPath = new BeanPath("[userInfo][examInfoDict][0]['id']");
|
||||||
|
Assertions.assertEquals("userInfo", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[examInfoDict][0]['id']", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("examInfoDict", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[0]['id']", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("0", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("['id']", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("id", beanPath.getNode().toString());
|
||||||
|
Assertions.assertNull(beanPath.getChild());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rangePathTest() {
|
||||||
|
BeanPath beanPath = new BeanPath("[userInfo][2:3]");
|
||||||
|
Assertions.assertEquals("userInfo", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[2:3]", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("[2:3:1]", beanPath.getNode().toString());
|
||||||
|
Assertions.assertNull(beanPath.getChild());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listPathTest() {
|
||||||
|
BeanPath beanPath = new BeanPath("[userInfo][1,2,3]");
|
||||||
|
Assertions.assertEquals("userInfo", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("[1,2,3]", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("[1, 2, 3]", beanPath.getNode().toString());
|
||||||
|
Assertions.assertNull(beanPath.getChild());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listKeysPathTest() {
|
||||||
|
BeanPath beanPath = new BeanPath("[userInfo]['a', 'b', 'c']");
|
||||||
|
Assertions.assertEquals("userInfo", beanPath.getNode().toString());
|
||||||
|
Assertions.assertEquals("['a', 'b', 'c']", beanPath.getChild());
|
||||||
|
|
||||||
|
beanPath = beanPath.next();
|
||||||
|
Assertions.assertEquals("[a, b, c]", beanPath.getNode().toString());
|
||||||
|
Assertions.assertNull(beanPath.getChild());
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.json;
|
package org.dromara.hutool.json;
|
||||||
|
|
||||||
import org.dromara.hutool.core.bean.BeanPath;
|
import org.dromara.hutool.core.bean.BeanPathOld;
|
||||||
import org.dromara.hutool.core.convert.ConvertException;
|
import org.dromara.hutool.core.convert.ConvertException;
|
||||||
import org.dromara.hutool.core.convert.Converter;
|
import org.dromara.hutool.core.convert.Converter;
|
||||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||||
@ -64,11 +64,11 @@ public interface JSON extends Converter, Cloneable, Serializable {
|
|||||||
*
|
*
|
||||||
* @param expression 表达式
|
* @param expression 表达式
|
||||||
* @return 对象
|
* @return 对象
|
||||||
* @see BeanPath#get(Object)
|
* @see BeanPathOld#get(Object)
|
||||||
* @since 4.0.6
|
* @since 4.0.6
|
||||||
*/
|
*/
|
||||||
default Object getByPath(final String expression) {
|
default Object getByPath(final String expression) {
|
||||||
return BeanPath.of(expression).get(this);
|
return BeanPathOld.of(expression).get(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,7 +93,7 @@ public interface JSON extends Converter, Cloneable, Serializable {
|
|||||||
* @param value 值
|
* @param value 值
|
||||||
*/
|
*/
|
||||||
default void putByPath(final String expression, final Object value) {
|
default void putByPath(final String expression, final Object value) {
|
||||||
BeanPath.of(expression).set(this, value);
|
BeanPathOld.of(expression).set(this, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,7 +118,7 @@ public interface JSON extends Converter, Cloneable, Serializable {
|
|||||||
* @param expression 表达式
|
* @param expression 表达式
|
||||||
* @param resultType 返回值类型
|
* @param resultType 返回值类型
|
||||||
* @return 对象
|
* @return 对象
|
||||||
* @see BeanPath#get(Object)
|
* @see BeanPathOld#get(Object)
|
||||||
* @since 4.0.6
|
* @since 4.0.6
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
Loading…
Reference in New Issue
Block a user