mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
修复xml转json再转bean失败问题
This commit is contained in:
parent
bd50e7f474
commit
fbe0d5d3cd
@ -77,11 +77,14 @@ public class BeanUtil {
|
|||||||
* @see #hasPublicField(Class)
|
* @see #hasPublicField(Class)
|
||||||
*/
|
*/
|
||||||
public static boolean isReadableBean(final Class<?> clazz) {
|
public static boolean isReadableBean(final Class<?> clazz) {
|
||||||
|
if(null == clazz){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return hasGetter(clazz) || hasPublicField(clazz);
|
return hasGetter(clazz) || hasPublicField(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断是否为Bean对象,判定方法是:
|
* 判断是否为可写Bean对象,判定方法是:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* 1、是否存在只有一个参数的setXXX方法
|
* 1、是否存在只有一个参数的setXXX方法
|
||||||
@ -93,7 +96,10 @@ public class BeanUtil {
|
|||||||
* @see #hasSetter(Class)
|
* @see #hasSetter(Class)
|
||||||
* @see #hasPublicField(Class)
|
* @see #hasPublicField(Class)
|
||||||
*/
|
*/
|
||||||
public static boolean isBean(final Class<?> clazz) {
|
public static boolean isWritableBean(final Class<?> clazz) {
|
||||||
|
if(null == clazz){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return hasSetter(clazz) || hasPublicField(clazz);
|
return hasSetter(clazz) || hasPublicField(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ package org.dromara.hutool.core.bean.copier;
|
|||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
import org.dromara.hutool.core.bean.BeanUtil;
|
||||||
import org.dromara.hutool.core.bean.PropDesc;
|
import org.dromara.hutool.core.bean.PropDesc;
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||||
import org.dromara.hutool.core.map.CaseInsensitiveMap;
|
import org.dromara.hutool.core.map.CaseInsensitiveMap;
|
||||||
import org.dromara.hutool.core.map.MapWrapper;
|
import org.dromara.hutool.core.map.MapWrapper;
|
||||||
|
@ -15,6 +15,7 @@ package org.dromara.hutool.core.collection;
|
|||||||
import org.dromara.hutool.core.array.ArrayUtil;
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
import org.dromara.hutool.core.bean.BeanUtil;
|
||||||
import org.dromara.hutool.core.codec.hash.Hash32;
|
import org.dromara.hutool.core.codec.hash.Hash32;
|
||||||
|
import org.dromara.hutool.core.collection.iter.ArrayIter;
|
||||||
import org.dromara.hutool.core.collection.iter.IterUtil;
|
import org.dromara.hutool.core.collection.iter.IterUtil;
|
||||||
import org.dromara.hutool.core.collection.iter.IteratorEnumeration;
|
import org.dromara.hutool.core.collection.iter.IteratorEnumeration;
|
||||||
import org.dromara.hutool.core.collection.queue.BoundedPriorityQueue;
|
import org.dromara.hutool.core.collection.queue.BoundedPriorityQueue;
|
||||||
@ -1553,6 +1554,10 @@ public class CollUtil {
|
|||||||
// String按照逗号分隔的列表对待
|
// String按照逗号分隔的列表对待
|
||||||
final String arrayStr = StrUtil.unWrap((CharSequence) value, '[', ']');
|
final String arrayStr = StrUtil.unWrap((CharSequence) value, '[', ']');
|
||||||
iter = SplitUtil.splitTrim(arrayStr, StrUtil.COMMA).iterator();
|
iter = SplitUtil.splitTrim(arrayStr, StrUtil.COMMA).iterator();
|
||||||
|
} else if(value instanceof Map && BeanUtil.isWritableBean(TypeUtil.getClass(elementType))){
|
||||||
|
//https://github.com/dromara/hutool/issues/3139
|
||||||
|
// 如果值为Map,而目标为一个Bean,则Map应整体转换为Bean,而非拆分成Entry转换
|
||||||
|
iter = new ArrayIter<>(new Object[]{value});
|
||||||
} else {
|
} else {
|
||||||
iter = IterUtil.getIter(value);
|
iter = IterUtil.getIter(value);
|
||||||
}
|
}
|
||||||
@ -2032,7 +2037,7 @@ public class CollUtil {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hash32(final T t) {
|
public int hash32(final T t) {
|
||||||
if (null == t || !BeanUtil.isBean(t.getClass())) {
|
if (null == t || !BeanUtil.isWritableBean(t.getClass())) {
|
||||||
// 非Bean放在同一子分组中
|
// 非Bean放在同一子分组中
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ public class CompositeConverter extends RegisterConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 尝试转Bean
|
// 尝试转Bean
|
||||||
if (BeanUtil.isBean(rowType)) {
|
if (BeanUtil.isWritableBean(rowType)) {
|
||||||
return (T) BeanConverter.INSTANCE.convert(type, value);
|
return (T) BeanConverter.INSTANCE.convert(type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ import org.dromara.hutool.core.lang.Assert;
|
|||||||
import org.dromara.hutool.core.map.MapProxy;
|
import org.dromara.hutool.core.map.MapProxy;
|
||||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
import org.dromara.hutool.core.reflect.kotlin.KClassUtil;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
@ -87,7 +86,7 @@ public class BeanConverter implements Converter, Serializable {
|
|||||||
private Object convertInternal(final Type targetType, final Class<?> targetClass, final Object value) {
|
private Object convertInternal(final Type targetType, final Class<?> targetClass, final Object value) {
|
||||||
if (value instanceof Map ||
|
if (value instanceof Map ||
|
||||||
value instanceof ValueProvider ||
|
value instanceof ValueProvider ||
|
||||||
BeanUtil.isBean(value.getClass())) {
|
BeanUtil.isWritableBean(value.getClass())) {
|
||||||
if (value instanceof Map && targetClass.isInterface()) {
|
if (value instanceof Map && targetClass.isInterface()) {
|
||||||
// 将Map动态代理为Bean
|
// 将Map动态代理为Bean
|
||||||
return MapProxy.of((Map<?, ?>) value).toProxyBean(targetClass);
|
return MapProxy.of((Map<?, ?>) value).toProxyBean(targetClass);
|
||||||
|
@ -77,7 +77,7 @@ public class EntryConverter implements Converter {
|
|||||||
} else if (value instanceof CharSequence) {
|
} else if (value instanceof CharSequence) {
|
||||||
final CharSequence str = (CharSequence) value;
|
final CharSequence str = (CharSequence) value;
|
||||||
map = strToMap(str);
|
map = strToMap(str);
|
||||||
} else if (BeanUtil.isBean(value.getClass())) {
|
} else if (BeanUtil.isWritableBean(value.getClass())) {
|
||||||
map = BeanUtil.beanToMap(value);
|
map = BeanUtil.beanToMap(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public class KBeanConverter implements Converter, Serializable {
|
|||||||
valueProvider = (ValueProvider<String>) value;
|
valueProvider = (ValueProvider<String>) value;
|
||||||
} else if(value instanceof Map){
|
} else if(value instanceof Map){
|
||||||
valueProvider = new MapValueProvider((Map<String, ?>) value);
|
valueProvider = new MapValueProvider((Map<String, ?>) value);
|
||||||
} else if(BeanUtil.isBean(value.getClass())){
|
} else if(BeanUtil.isWritableBean(value.getClass())){
|
||||||
valueProvider = new BeanValueProvider(value);
|
valueProvider = new BeanValueProvider(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ public class MapConverter implements Converter, Serializable {
|
|||||||
|
|
||||||
map = MapUtil.createMap(TypeUtil.getClass(targetType), LinkedHashMap::new);
|
map = MapUtil.createMap(TypeUtil.getClass(targetType), LinkedHashMap::new);
|
||||||
convertMapToMap(keyType, valueType, (Map) value, map);
|
convertMapToMap(keyType, valueType, (Map) value, map);
|
||||||
} else if (BeanUtil.isBean(value.getClass())) {
|
} else if (BeanUtil.isWritableBean(value.getClass())) {
|
||||||
map = BeanUtil.beanToMap(value);
|
map = BeanUtil.beanToMap(value);
|
||||||
// 二次转换,转换键值类型
|
// 二次转换,转换键值类型
|
||||||
map = convert(targetType, keyType, valueType, map);
|
map = convert(targetType, keyType, valueType, map);
|
||||||
|
@ -46,7 +46,7 @@ public class RecordConverter extends AbstractConverter {
|
|||||||
valueProvider = (ValueProvider<String>) value;
|
valueProvider = (ValueProvider<String>) value;
|
||||||
} else if (value instanceof Map) {
|
} else if (value instanceof Map) {
|
||||||
valueProvider = new MapValueProvider((Map<String, ?>) value);
|
valueProvider = new MapValueProvider((Map<String, ?>) value);
|
||||||
} else if (BeanUtil.isBean(value.getClass())) {
|
} else if (BeanUtil.isWritableBean(value.getClass())) {
|
||||||
valueProvider = new BeanValueProvider(value);
|
valueProvider = new BeanValueProvider(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import org.dromara.hutool.core.io.resource.ResourceUtil;
|
|||||||
import org.dromara.hutool.core.io.stream.BOMInputStream;
|
import org.dromara.hutool.core.io.stream.BOMInputStream;
|
||||||
import org.dromara.hutool.core.io.unit.DataSizeUtil;
|
import org.dromara.hutool.core.io.unit.DataSizeUtil;
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
import org.dromara.hutool.core.net.url.URLUtil;
|
import org.dromara.hutool.core.net.url.URLUtil;
|
||||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
import org.dromara.hutool.core.reflect.ClassUtil;
|
||||||
import org.dromara.hutool.core.regex.ReUtil;
|
import org.dromara.hutool.core.regex.ReUtil;
|
||||||
@ -142,6 +143,7 @@ public class FileUtil extends PathUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// region ----- loop and walk
|
// region ----- loop and walk
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 递归遍历目录以及子目录中的所有文件<br>
|
* 递归遍历目录以及子目录中的所有文件<br>
|
||||||
* 如果提供file为文件,直接返回过滤结果
|
* 如果提供file为文件,直接返回过滤结果
|
||||||
@ -273,6 +275,7 @@ public class FileUtil extends PathUtil {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region ----- file and newFile
|
// region ----- file and newFile
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建File对象,相当于调用new File(),不做任何处理
|
* 创建File对象,相当于调用new File(),不做任何处理
|
||||||
*
|
*
|
||||||
@ -419,6 +422,7 @@ public class FileUtil extends PathUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// region ----- exists
|
// region ----- exists
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断文件是否存在,如果path为null,则返回false
|
* 判断文件是否存在,如果path为null,则返回false
|
||||||
*
|
*
|
||||||
@ -468,6 +472,7 @@ public class FileUtil extends PathUtil {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region ----- lastModifiedTime
|
// region ----- lastModifiedTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指定文件最后修改时间
|
* 指定文件最后修改时间
|
||||||
*
|
*
|
||||||
@ -590,6 +595,7 @@ public class FileUtil extends PathUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// region ----- touch
|
// region ----- touch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建文件及其父目录,如果这个文件存在,直接返回这个文件<br>
|
* 创建文件及其父目录,如果这个文件存在,直接返回这个文件<br>
|
||||||
* 此方法不对File对象类型做判断,如果File不存在,无法判断其类型
|
* 此方法不对File对象类型做判断,如果File不存在,无法判断其类型
|
||||||
@ -803,6 +809,7 @@ public class FileUtil extends PathUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// region ----- createTempFile
|
// region ----- createTempFile
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建临时文件<br>
|
* 创建临时文件<br>
|
||||||
* 创建后的文件名为 prefix[Random].tmp
|
* 创建后的文件名为 prefix[Random].tmp
|
||||||
@ -1501,6 +1508,7 @@ public class FileUtil extends PathUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// region ----- in
|
// region ----- in
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得输入流
|
* 获得输入流
|
||||||
*
|
*
|
||||||
@ -1598,6 +1606,7 @@ public class FileUtil extends PathUtil {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region ----- read
|
// region ----- read
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取文件所有数据<br>
|
* 读取文件所有数据<br>
|
||||||
* 文件的长度不能超过Integer.MAX_VALUE
|
* 文件的长度不能超过Integer.MAX_VALUE
|
||||||
@ -2101,6 +2110,7 @@ public class FileUtil extends PathUtil {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region ----- write and append
|
// region ----- write and append
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将String写入文件,覆盖模式,字符集为UTF-8
|
* 将String写入文件,覆盖模式,字符集为UTF-8
|
||||||
*
|
*
|
||||||
@ -2638,13 +2648,25 @@ public class FileUtil extends PathUtil {
|
|||||||
*/
|
*/
|
||||||
public static File checkSlip(final File parentFile, final File file) throws IllegalArgumentException {
|
public static File checkSlip(final File parentFile, final File file) throws IllegalArgumentException {
|
||||||
if (null != parentFile && null != file) {
|
if (null != parentFile && null != file) {
|
||||||
if(!file.toPath().startsWith(parentFile.toPath())){
|
if (!startsWith(parentFile, file)) {
|
||||||
throw new IllegalArgumentException("New file is outside of the parent dir: " + file.getName());
|
throw new IllegalArgumentException("New file is outside of the parent dir: " + file.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查父文件是否为文件真正的父目录
|
||||||
|
*
|
||||||
|
* @param parentFile 父目录
|
||||||
|
* @param file 文件
|
||||||
|
* @return 是否为文件真正的父目录
|
||||||
|
*/
|
||||||
|
public static boolean startsWith(final File parentFile, final File file) {
|
||||||
|
return PathUtil.toAbsNormal(parentFile.toPath())
|
||||||
|
.startsWith(PathUtil.toAbsNormal(file.toPath()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据文件扩展名获得MimeType
|
* 根据文件扩展名获得MimeType
|
||||||
*
|
*
|
||||||
|
@ -32,6 +32,7 @@ import java.util.List;
|
|||||||
* @since 5.4.1
|
* @since 5.4.1
|
||||||
*/
|
*/
|
||||||
public class PathUtil {
|
public class PathUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 目录是否为空
|
* 目录是否为空
|
||||||
*
|
*
|
||||||
@ -559,10 +560,30 @@ public class PathUtil {
|
|||||||
* @since 5.5.5
|
* @since 5.5.5
|
||||||
*/
|
*/
|
||||||
public static Path toAbsNormal(final Path path) {
|
public static Path toAbsNormal(final Path path) {
|
||||||
Assert.notNull(path);
|
if (null == path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return path.toAbsolutePath().normalize();
|
return path.toAbsolutePath().normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取实际路径,路径文件必须存在
|
||||||
|
*
|
||||||
|
* @param path 路径
|
||||||
|
* @return 实际路径
|
||||||
|
* @throws IORuntimeException IO异常,如文件不存在等
|
||||||
|
*/
|
||||||
|
public static Path toRealPath(Path path) throws IORuntimeException{
|
||||||
|
if (null != path) {
|
||||||
|
try {
|
||||||
|
path = path.toRealPath();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throw new IORuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得文件的MimeType
|
* 获得文件的MimeType
|
||||||
*
|
*
|
||||||
|
@ -39,7 +39,7 @@ public class BeanUtilTest {
|
|||||||
public void isBeanTest() {
|
public void isBeanTest() {
|
||||||
|
|
||||||
// HashMap不包含setXXX方法,不是bean
|
// HashMap不包含setXXX方法,不是bean
|
||||||
final boolean isBean = BeanUtil.isBean(HashMap.class);
|
final boolean isBean = BeanUtil.isWritableBean(HashMap.class);
|
||||||
Assertions.assertFalse(isBean);
|
Assertions.assertFalse(isBean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,15 +24,16 @@ import java.util.List;
|
|||||||
public class FileUtilTest {
|
public class FileUtilTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fileTest() {
|
void fileTest1() {
|
||||||
Assertions.assertThrows(IllegalArgumentException.class, ()->{
|
|
||||||
final File file = FileUtil.file("d:/aaa", "bbb");
|
final File file = FileUtil.file("d:/aaa", "bbb");
|
||||||
Assertions.assertNotNull(file);
|
Assertions.assertNotNull(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fileTest2() {
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class, ()->{
|
||||||
// 构建目录中出现非子目录抛出异常
|
// 构建目录中出现非子目录抛出异常
|
||||||
FileUtil.file(file, "../ccc");
|
FileUtil.file("d:/aaa/bbb", "../ccc");
|
||||||
|
|
||||||
FileUtil.file("E:/");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import org.xml.sax.helpers.DefaultHandler;
|
|||||||
|
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -380,4 +381,29 @@ public class XmlUtilTest {
|
|||||||
private String age;
|
private String age;
|
||||||
private String email;
|
private String email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void issue3139Test() {
|
||||||
|
final String xml = "<r>\n" +
|
||||||
|
" <c>\n" +
|
||||||
|
" <s>1</s>\n" +
|
||||||
|
" <p>str</p>\n" +
|
||||||
|
" </c>\n" +
|
||||||
|
"</r>";
|
||||||
|
|
||||||
|
final R r = XmlUtil.xmlToBean(XmlUtil.parseXml(xml), R.class);
|
||||||
|
Assertions.assertEquals("1", r.getC().get(0).getS());
|
||||||
|
Assertions.assertEquals("str", r.getC().get(0).getP());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class C {
|
||||||
|
String s;
|
||||||
|
String p;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class R {
|
||||||
|
List<C> c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ public class JSONConverter implements Converter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 尝试转Bean
|
// 尝试转Bean
|
||||||
if (BeanUtil.isBean(rawType)) {
|
if (BeanUtil.isWritableBean(rawType)) {
|
||||||
// issue#I5WDP0 对于Kotlin对象,由于参数可能非空限制,导致无法创建一个默认的对象再赋值
|
// issue#I5WDP0 对于Kotlin对象,由于参数可能非空限制,导致无法创建一个默认的对象再赋值
|
||||||
if(KClassUtil.isKotlinClass(rawType) && json instanceof JSONGetter){
|
if(KClassUtil.isKotlinClass(rawType) && json instanceof JSONGetter){
|
||||||
return KClassUtil.newInstance(rawType, new JSONGetterValueProvider<>((JSONGetter<String>)json));
|
return KClassUtil.newInstance(rawType, new JSONGetterValueProvider<>((JSONGetter<String>)json));
|
||||||
|
53
hutool-json/src/test/java/org/dromara/hutool/json/Issue3139Test.java
Executable file
53
hutool-json/src/test/java/org/dromara/hutool/json/Issue3139Test.java
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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:
|
||||||
|
* http://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.json;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
|
import org.dromara.hutool.core.util.XmlUtil;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Issue3139Test {
|
||||||
|
@Test
|
||||||
|
public void toBeanTest() {
|
||||||
|
final String xml = "<r>\n" +
|
||||||
|
" <c>\n" +
|
||||||
|
" <s>1</s>\n" +
|
||||||
|
" <p>str</p>\n" +
|
||||||
|
" </c>\n" +
|
||||||
|
"</r>";
|
||||||
|
|
||||||
|
final JSONObject jsonObject = XmlUtil.xmlToBean(XmlUtil.parseXml(xml).getDocumentElement(), JSONObject.class);
|
||||||
|
final R bean = jsonObject.toBean(R.class);
|
||||||
|
Assertions.assertNotNull(bean);
|
||||||
|
|
||||||
|
final List<C> c = bean.getC();
|
||||||
|
Assertions.assertEquals(1, c.size());
|
||||||
|
Assertions.assertEquals("1", c.get(0).getS());
|
||||||
|
Assertions.assertEquals("str", c.get(0).getP());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class C {
|
||||||
|
String s;
|
||||||
|
String p;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class R {
|
||||||
|
List<C> c;
|
||||||
|
}
|
||||||
|
}
|
@ -991,7 +991,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
|
|||||||
} else if (rowBean instanceof Hyperlink) {
|
} else if (rowBean instanceof Hyperlink) {
|
||||||
// Hyperlink当成一个值
|
// Hyperlink当成一个值
|
||||||
return writeRow(ListUtil.of(rowBean), isWriteKeyAsHead);
|
return writeRow(ListUtil.of(rowBean), isWriteKeyAsHead);
|
||||||
} else if (BeanUtil.isBean(rowBean.getClass())) {
|
} else if (BeanUtil.isWritableBean(rowBean.getClass())) {
|
||||||
if (MapUtil.isEmpty(this.headerAlias)) {
|
if (MapUtil.isEmpty(this.headerAlias)) {
|
||||||
rowMap = BeanUtil.beanToMap(rowBean, new LinkedHashMap<>(), false, false);
|
rowMap = BeanUtil.beanToMap(rowBean, new LinkedHashMap<>(), false, false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -102,7 +102,7 @@ public class TableUtil {
|
|||||||
final Map rowMap;
|
final Map rowMap;
|
||||||
if(rowBean instanceof Map) {
|
if(rowBean instanceof Map) {
|
||||||
rowMap = (Map) rowBean;
|
rowMap = (Map) rowBean;
|
||||||
} else if (BeanUtil.isBean(rowBean.getClass())) {
|
} else if (BeanUtil.isWritableBean(rowBean.getClass())) {
|
||||||
rowMap = BeanUtil.beanToMap(rowBean, new LinkedHashMap<>(), false, false);
|
rowMap = BeanUtil.beanToMap(rowBean, new LinkedHashMap<>(), false, false);
|
||||||
} else {
|
} else {
|
||||||
// 其它转为字符串默认输出
|
// 其它转为字符串默认输出
|
||||||
|
Loading…
x
Reference in New Issue
Block a user