mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
修复Pair序列化转换无效问题
This commit is contained in:
parent
2665469612
commit
1804b7e6da
@ -15,7 +15,9 @@ package org.dromara.hutool.core.convert;
|
|||||||
import org.dromara.hutool.core.convert.impl.*;
|
import org.dromara.hutool.core.convert.impl.*;
|
||||||
import org.dromara.hutool.core.date.DateTime;
|
import org.dromara.hutool.core.date.DateTime;
|
||||||
import org.dromara.hutool.core.lang.Opt;
|
import org.dromara.hutool.core.lang.Opt;
|
||||||
|
import org.dromara.hutool.core.lang.tuple.Pair;
|
||||||
import org.dromara.hutool.core.map.SafeConcurrentHashMap;
|
import org.dromara.hutool.core.map.SafeConcurrentHashMap;
|
||||||
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
|
|
||||||
import javax.xml.datatype.XMLGregorianCalendar;
|
import javax.xml.datatype.XMLGregorianCalendar;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -65,7 +67,7 @@ public class RegisterConverter implements Converter, Serializable {
|
|||||||
/**
|
/**
|
||||||
* 默认类型转换器
|
* 默认类型转换器
|
||||||
*/
|
*/
|
||||||
private Map<Type, Converter> defaultConverterMap;
|
private Map<Class<?>, Converter> defaultConverterMap;
|
||||||
/**
|
/**
|
||||||
* 用户自定义类型转换器
|
* 用户自定义类型转换器
|
||||||
*/
|
*/
|
||||||
@ -120,7 +122,7 @@ public class RegisterConverter implements Converter, Serializable {
|
|||||||
* @return 转换器
|
* @return 转换器
|
||||||
*/
|
*/
|
||||||
public Converter getDefaultConverter(final Type type) {
|
public Converter getDefaultConverter(final Type type) {
|
||||||
return (null == defaultConverterMap) ? null : defaultConverterMap.get(type);
|
return (null == defaultConverterMap) ? null : defaultConverterMap.get(TypeUtil.getClass(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,5 +216,6 @@ public class RegisterConverter implements Converter, Serializable {
|
|||||||
defaultConverterMap.put(StackTraceElement.class, new StackTraceElementConverter());// since 4.5.2
|
defaultConverterMap.put(StackTraceElement.class, new StackTraceElementConverter());// since 4.5.2
|
||||||
defaultConverterMap.put(Optional.class, new OptionalConverter());// since 5.0.0
|
defaultConverterMap.put(Optional.class, new OptionalConverter());// since 5.0.0
|
||||||
defaultConverterMap.put(Opt.class, new OptConverter());// since 5.7.16
|
defaultConverterMap.put(Opt.class, new OptConverter());// since 5.7.16
|
||||||
|
defaultConverterMap.put(Pair.class, PairConverter.INSTANCE);// since 5.7.16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import org.dromara.hutool.core.bean.BeanUtil;
|
|||||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
import org.dromara.hutool.core.convert.CompositeConverter;
|
||||||
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.tuple.Pair;
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||||
import org.dromara.hutool.core.reflect.TypeReference;
|
import org.dromara.hutool.core.reflect.TypeReference;
|
||||||
@ -72,6 +73,9 @@ public class EntryConverter implements Converter {
|
|||||||
if (value instanceof Map.Entry) {
|
if (value instanceof Map.Entry) {
|
||||||
final Map.Entry entry = (Map.Entry) value;
|
final Map.Entry entry = (Map.Entry) value;
|
||||||
map = MapUtil.of(entry.getKey(), entry.getValue());
|
map = MapUtil.of(entry.getKey(), entry.getValue());
|
||||||
|
}else if (value instanceof Pair) {
|
||||||
|
final Pair entry = (Pair<?, ?>) value;
|
||||||
|
map = MapUtil.of(entry.getLeft(), entry.getRight());
|
||||||
}else if (value instanceof Map) {
|
}else if (value instanceof Map) {
|
||||||
map = (Map) value;
|
map = (Map) value;
|
||||||
} else if (value instanceof CharSequence) {
|
} else if (value instanceof CharSequence) {
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* 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.core.convert.impl;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.bean.BeanUtil;
|
||||||
|
import org.dromara.hutool.core.convert.CompositeConverter;
|
||||||
|
import org.dromara.hutool.core.convert.ConvertException;
|
||||||
|
import org.dromara.hutool.core.convert.Converter;
|
||||||
|
import org.dromara.hutool.core.lang.tuple.Pair;
|
||||||
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
|
import org.dromara.hutool.core.reflect.TypeReference;
|
||||||
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
|
import org.dromara.hutool.core.text.CharUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Pair} 转换器,支持以下类型转为Pair
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link Map}</li>
|
||||||
|
* <li>{@link Map.Entry}</li>
|
||||||
|
* <li>带分隔符的字符串,支持分隔符{@code :}、{@code =}、{@code ,}</li>
|
||||||
|
* <li>Bean,包含{@code getKey}和{@code getValue}方法</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
*/
|
||||||
|
public class PairConverter implements Converter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单例
|
||||||
|
*/
|
||||||
|
public static final PairConverter INSTANCE = new PairConverter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convert(Type targetType, final Object value) throws ConvertException {
|
||||||
|
if (targetType instanceof TypeReference) {
|
||||||
|
targetType = ((TypeReference<?>) targetType).getType();
|
||||||
|
}
|
||||||
|
final Type keyType = TypeUtil.getTypeArgument(targetType, 0);
|
||||||
|
final Type valueType = TypeUtil.getTypeArgument(targetType, 1);
|
||||||
|
|
||||||
|
return convert(keyType, valueType, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换对象为指定键值类型的指定类型Map
|
||||||
|
*
|
||||||
|
* @param keyType 键类型
|
||||||
|
* @param valueType 值类型
|
||||||
|
* @param value 被转换的值
|
||||||
|
* @return 转换后的Map
|
||||||
|
* @throws ConvertException 转换异常或不支持的类型
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public Pair<?, ?> convert(final Type keyType, final Type valueType, final Object value)
|
||||||
|
throws ConvertException {
|
||||||
|
Map map = null;
|
||||||
|
if (value instanceof Map.Entry) {
|
||||||
|
final Map.Entry entry = (Map.Entry) value;
|
||||||
|
map = MapUtil.of(entry.getKey(), entry.getValue());
|
||||||
|
} else if (value instanceof Pair) {
|
||||||
|
final Pair entry = (Pair<?, ?>) value;
|
||||||
|
map = MapUtil.of(entry.getLeft(), entry.getRight());
|
||||||
|
} else if (value instanceof Map) {
|
||||||
|
map = (Map) value;
|
||||||
|
} else if (value instanceof CharSequence) {
|
||||||
|
final CharSequence str = (CharSequence) value;
|
||||||
|
map = strToMap(str);
|
||||||
|
} else if (BeanUtil.isWritableBean(value.getClass())) {
|
||||||
|
map = BeanUtil.beanToMap(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != map) {
|
||||||
|
return mapToPair(keyType, valueType, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ConvertException("Unsupported to map from [{}] of type: {}", value, value.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转单个键值对的Map,支持分隔符{@code :}、{@code =}、{@code ,}
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @return map or null
|
||||||
|
*/
|
||||||
|
private static Map<CharSequence, CharSequence> strToMap(final CharSequence str) {
|
||||||
|
// key:value key=value key,value
|
||||||
|
final int index = StrUtil.indexOf(str,
|
||||||
|
c -> c == CharUtil.COLON || c == CharUtil.EQUAL || c == CharUtil.COMMA,
|
||||||
|
0, str.length());
|
||||||
|
|
||||||
|
if (index > -1) {
|
||||||
|
return MapUtil.of(str.subSequence(0, index), str.subSequence(index + 1, str.length()));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map转Entry
|
||||||
|
*
|
||||||
|
* @param keyType 键类型
|
||||||
|
* @param valueType 值类型
|
||||||
|
* @param map 被转换的map
|
||||||
|
* @return Entry
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private static Pair<?, ?> mapToPair(final Type keyType, final Type valueType, final Map map) {
|
||||||
|
|
||||||
|
Object left = null;
|
||||||
|
Object right = null;
|
||||||
|
if (1 == map.size()) {
|
||||||
|
final Map.Entry entry = (Map.Entry) map.entrySet().iterator().next();
|
||||||
|
left = entry.getKey();
|
||||||
|
right = entry.getValue();
|
||||||
|
} else if (2 == map.size()) {
|
||||||
|
left = map.get("left");
|
||||||
|
right = map.get("right");
|
||||||
|
}
|
||||||
|
|
||||||
|
final CompositeConverter convert = CompositeConverter.getInstance();
|
||||||
|
return Pair.of(
|
||||||
|
TypeUtil.isUnknown(keyType) ? left : convert.convert(keyType, left),
|
||||||
|
TypeUtil.isUnknown(valueType) ? right : convert.convert(valueType, right)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
28
hutool-json/src/test/java/org/dromara/hutool/json/IssueI7GPGXTest.java
Executable file
28
hutool-json/src/test/java/org/dromara/hutool/json/IssueI7GPGXTest.java
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.dromara.hutool.core.lang.tuple.Pair;
|
||||||
|
import org.dromara.hutool.core.reflect.TypeReference;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class IssueI7GPGXTest {
|
||||||
|
@Test
|
||||||
|
public void pairToBeanTest() {
|
||||||
|
final Pair<String, Boolean> hutoolPair = new Pair<>("test1", true);
|
||||||
|
final String a = JSONUtil.toJsonStr(hutoolPair);
|
||||||
|
final Pair<String, Boolean> pair = JSONUtil.toBean(a, new TypeReference<Pair<String, Boolean>>() {});
|
||||||
|
Assertions.assertEquals(hutoolPair, pair);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user