mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
f770e00904
commit
2fdbb46259
@ -62,19 +62,19 @@ public class ValueProviderToBeanCopier<T> extends AbsCopier<ValueProvider<String
|
||||
}
|
||||
final Map<String, PropDesc> targetPropDescMap = getBeanDesc(actualEditable).getPropMap(copyOptions.ignoreCase);
|
||||
|
||||
targetPropDescMap.forEach((tFieldName, tDesc) -> {
|
||||
targetPropDescMap.forEach((tFieldName, propDesc) -> {
|
||||
if (null == tFieldName) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查目标字段可写性
|
||||
if (null == tDesc || !tDesc.isWritable(this.copyOptions.transientSupport)) {
|
||||
if (null == propDesc || !propDesc.isWritable(this.copyOptions.transientSupport)) {
|
||||
// 字段不可写,跳过之
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取目标字段真实类型
|
||||
final Type fieldType = TypeUtil.getActualType(this.targetType ,tDesc.getFieldType());
|
||||
final Type fieldType = TypeUtil.getActualType(this.targetType ,propDesc.getFieldType());
|
||||
// 编辑键值对
|
||||
final MutableEntry<Object, Object> entry = copyOptions.editField(tFieldName, null);
|
||||
if(null == entry){
|
||||
@ -92,12 +92,12 @@ public class ValueProviderToBeanCopier<T> extends AbsCopier<ValueProvider<String
|
||||
final Object sValue = source.value(tFieldName, fieldType);
|
||||
|
||||
// 检查目标对象属性是否过滤属性
|
||||
if (!copyOptions.testPropertyFilter(tDesc.getField(), sValue)) {
|
||||
if (!copyOptions.testPropertyFilter(propDesc.getField(), sValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 目标赋值
|
||||
tDesc.setValue(this.target, sValue, copyOptions.ignoreNullValue, copyOptions.ignoreError, copyOptions.override);
|
||||
propDesc.setValue(this.target, sValue, copyOptions.ignoreNullValue, copyOptions.ignoreError, copyOptions.override);
|
||||
});
|
||||
return this.target;
|
||||
}
|
||||
|
@ -29,14 +29,31 @@ import java.util.Date;
|
||||
* 日期转换器
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class CalendarConverter extends AbstractConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 日期格式化 */
|
||||
/**
|
||||
* 日期格式化
|
||||
*/
|
||||
private String format;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public CalendarConverter() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param format 日期格式,{@code null}表示无格式定义
|
||||
*/
|
||||
public CalendarConverter(final String format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日期格式
|
||||
*
|
||||
@ -59,16 +76,16 @@ public class CalendarConverter extends AbstractConverter {
|
||||
protected Calendar convertInternal(final Class<?> targetClass, final Object value) {
|
||||
// Handle Date
|
||||
if (value instanceof Date) {
|
||||
return CalendarUtil.calendar((Date)value);
|
||||
return CalendarUtil.calendar((Date) value);
|
||||
}
|
||||
|
||||
// Handle Long
|
||||
if (value instanceof Long) {
|
||||
//此处使用自动拆装箱
|
||||
return CalendarUtil.calendar((Long)value);
|
||||
return CalendarUtil.calendar((Long) value);
|
||||
}
|
||||
|
||||
if(value instanceof XMLGregorianCalendar){
|
||||
if (value instanceof XMLGregorianCalendar) {
|
||||
return CalendarUtil.calendar((XMLGregorianCalendar) value);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ public class DateConverter extends AbstractConverter implements MatcherConverter
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param format 日期格式
|
||||
* @param format 日期格式,{@code null}表示无格式定义
|
||||
*/
|
||||
public DateConverter(final String format) {
|
||||
this.format = format;
|
||||
|
@ -63,6 +63,8 @@ public class TypeUtil {
|
||||
}
|
||||
} else if(type instanceof GenericArrayType){
|
||||
return Array.newInstance(getClass(((GenericArrayType)type).getGenericComponentType()), 0).getClass();
|
||||
} else if(type instanceof TypeReference){
|
||||
return getClass(((TypeReference<?>)type).getType());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -429,6 +431,7 @@ public class TypeUtil {
|
||||
}
|
||||
|
||||
if (typeVariable instanceof TypeVariable) {
|
||||
// TODO TypeReference无效
|
||||
return ActualTypeMapperPool.getActualType(type, (TypeVariable<?>) typeVariable);
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,16 @@
|
||||
package org.dromara.hutool.core.util;
|
||||
|
||||
import org.dromara.hutool.core.collection.CollUtil;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.func.LambdaUtil;
|
||||
import org.dromara.hutool.core.func.SerFunction;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.reflect.FieldUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
@ -40,11 +42,11 @@ public class EnumUtil {
|
||||
/**
|
||||
* 指定类是否为Enum类
|
||||
*
|
||||
* @param clazz 类
|
||||
* @param type 类
|
||||
* @return 是否为Enum类
|
||||
*/
|
||||
public static boolean isEnum(final Class<?> clazz) {
|
||||
return Assert.notNull(clazz).isEnum();
|
||||
public static boolean isEnum(final Type type) {
|
||||
return Assert.notNull(TypeUtil.getClass(type)).isEnum();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,10 +16,11 @@
|
||||
|
||||
package org.dromara.hutool.core.util;
|
||||
|
||||
import org.dromara.hutool.core.reflect.FieldUtil;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import lombok.Data;
|
||||
import org.dromara.hutool.core.reflect.FieldUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeReference;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -27,9 +28,16 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TypeUtilTest {
|
||||
|
||||
@Test
|
||||
void getMapClassTest() {
|
||||
final Class<?> aClass = TypeUtil.getClass(new TypeReference<Map<String, String>>() {});
|
||||
Assertions.assertEquals(Map.class, aClass);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEleTypeTest() {
|
||||
final Method method = MethodUtil.getMethod(TestClass.class, "getList");
|
||||
|
@ -28,6 +28,7 @@ import org.dromara.hutool.core.text.CharUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.text.split.SplitUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.mapper.JSONValueMapper;
|
||||
import org.dromara.hutool.json.reader.JSONTokener;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -178,8 +179,7 @@ public final class InternalJSONUtil {
|
||||
.setIgnoreError(config.isIgnoreError())
|
||||
.setIgnoreNullValue(config.isIgnoreNullValue())
|
||||
.setTransientSupport(config.isTransientSupport())
|
||||
// 使用JSON转换器
|
||||
.setConverter(config.getConverter());
|
||||
.setConverter((targetType, value) -> JSONValueMapper.of(config, null).map(value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,10 +17,9 @@
|
||||
package org.dromara.hutool.json;
|
||||
|
||||
import org.dromara.hutool.core.bean.path.BeanPath;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.Converter;
|
||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -38,7 +37,7 @@ import java.util.function.Predicate;
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public interface JSON extends Converter, Serializable {
|
||||
public interface JSON extends Serializable {
|
||||
|
||||
/**
|
||||
* 获取JSON配置
|
||||
@ -64,6 +63,33 @@ public interface JSON extends Converter, Serializable {
|
||||
return 0 == size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为JSONObject
|
||||
*
|
||||
* @return JSONObject
|
||||
*/
|
||||
default JSONObject asJSONObject() {
|
||||
return (JSONObject) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为JSONArray
|
||||
*
|
||||
* @return JSONArray
|
||||
*/
|
||||
default JSONArray asJSONArray() {
|
||||
return (JSONArray) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为JSONPrimitive
|
||||
*
|
||||
* @return JSONPrimitive
|
||||
*/
|
||||
default JSONPrimitive asJSONPrimitive() {
|
||||
return (JSONPrimitive) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过表达式获取JSON中嵌套的对象<br>
|
||||
* <ol>
|
||||
@ -141,7 +167,13 @@ public interface JSON extends Converter, Serializable {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> T getByPath(final String expression, final Type resultType) {
|
||||
return (T) config().getConverter().convert(resultType, getByPath(expression));
|
||||
final JSON json = getByPath(expression);
|
||||
if (null == json) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final JSONDeserializer<Object> deserializer = TypeAdapterManager.getInstance().getDeserializer(json, resultType);
|
||||
return (T) deserializer.deserialize(json, resultType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -199,11 +231,10 @@ public interface JSON extends Converter, Serializable {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> T toBean(final Type type) {
|
||||
return (T) convert(type, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
default Object convert(final Type targetType, final Object value) throws ConvertException {
|
||||
return ObjUtil.defaultIfNull(config(), JSONConfig::of).getConverter().convert(targetType, value);
|
||||
final JSONDeserializer<Object> deserializer = TypeAdapterManager.getInstance().getDeserializer(this, type);
|
||||
if(null == deserializer){
|
||||
throw new JSONException("No deserializer for type: " + type);
|
||||
}
|
||||
return (T) deserializer.deserialize(this, type);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import org.dromara.hutool.core.convert.impl.ArrayConverter;
|
||||
import org.dromara.hutool.core.lang.Validator;
|
||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.mapper.JSONValueMapper;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
|
||||
import java.util.*;
|
||||
@ -51,6 +52,7 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
* 配置项
|
||||
*/
|
||||
private final JSONConfig config;
|
||||
private final JSONValueMapper mapper;
|
||||
|
||||
// region ----- Constructors
|
||||
|
||||
@ -95,6 +97,7 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
public JSONArray(final int initialCapacity, final JSONConfig config) {
|
||||
super(new ArrayList<>(initialCapacity));
|
||||
this.config = ObjUtil.defaultIfNull(config, JSONConfig::of);
|
||||
this.mapper = JSONValueMapper.of(config, null);
|
||||
}
|
||||
// endregion
|
||||
|
||||
@ -129,7 +132,7 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
* @since 5.2.5
|
||||
*/
|
||||
public JSONArray set(final Object value) {
|
||||
this.add(config.getConverter().convert(JSON.class, value));
|
||||
this.add(mapper.map(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -213,7 +216,7 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
* @return 替换的值,即之前的值
|
||||
*/
|
||||
public JSON setValue(final int index, final Object element) {
|
||||
return set(index, config.getConverter().convert(JSON.class, element));
|
||||
return set(index, mapper.map(element));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,8 +17,6 @@
|
||||
package org.dromara.hutool.json;
|
||||
|
||||
import org.dromara.hutool.core.comparator.CompareUtil;
|
||||
import org.dromara.hutool.core.convert.Converter;
|
||||
import org.dromara.hutool.json.convert.JSONConverter;
|
||||
import org.dromara.hutool.json.writer.NumberWriteMode;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -70,10 +68,6 @@ public class JSONConfig implements Serializable {
|
||||
* 是否检查重复key
|
||||
*/
|
||||
private boolean checkDuplicate;
|
||||
/**
|
||||
* 自定义的类型转换器,用于在getXXX操作中自动转换类型
|
||||
*/
|
||||
private Converter converter = JSONConverter.of(this);
|
||||
/**
|
||||
* Number写出模式
|
||||
*/
|
||||
@ -274,24 +268,6 @@ public class JSONConfig implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义的类型转换器,用于在序列化、反序列化操作中实现对象类型转换
|
||||
*
|
||||
* @return 转换器
|
||||
*/
|
||||
public Converter getConverter() {
|
||||
return converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自定义的类型转换器,用于在序列化、反序列化操作中实现对象类型转换
|
||||
*
|
||||
* @param converter 转换器
|
||||
*/
|
||||
public void setConverter(final Converter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Number写出模式
|
||||
*
|
||||
|
@ -16,8 +16,11 @@
|
||||
|
||||
package org.dromara.hutool.json;
|
||||
|
||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
||||
import org.dromara.hutool.core.lang.getter.TypeGetter;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
@ -144,13 +147,24 @@ public interface JSONGetter<K> extends TypeGetter<K> {
|
||||
return (null == jsonArray) ? null : jsonArray.toList(beanType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
default <T> T get(final K key, final Type type, final T defaultValue) {
|
||||
final Object value = this.getObj(key);
|
||||
Object value = this.getObj(key);
|
||||
if (ObjUtil.isNull(value)) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return get(key, type, config().getConverter(), defaultValue);
|
||||
if(value instanceof JSON){
|
||||
final JSONDeserializer<Object> deserializer = TypeAdapterManager.getInstance().getDeserializer((JSON) value, type);
|
||||
if(null == deserializer){
|
||||
throw new JSONException("No deserializer for type: " + type);
|
||||
}
|
||||
value = deserializer.deserialize((JSON) value, type);
|
||||
return null == value ? defaultValue : (T) value;
|
||||
}
|
||||
|
||||
// JSONPrimitive中的值
|
||||
return CompositeConverter.getInstance().convert(type, value, defaultValue);
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.map.MapWrapper;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.mapper.JSONValueMapper;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -52,6 +53,7 @@ public class JSONObject extends MapWrapper<String, JSON> implements JSON, JSONGe
|
||||
* 配置项
|
||||
*/
|
||||
private final JSONConfig config;
|
||||
private final JSONValueMapper mapper;
|
||||
|
||||
/**
|
||||
* 构造,初始容量为 {@link #DEFAULT_CAPACITY},KEY有序
|
||||
@ -79,6 +81,7 @@ public class JSONObject extends MapWrapper<String, JSON> implements JSON, JSONGe
|
||||
public JSONObject(final int capacity, final JSONConfig config) {
|
||||
super(InternalJSONUtil.createRawMap(capacity, config));
|
||||
this.config = ObjUtil.defaultIfNull(config, JSONConfig::of);
|
||||
this.mapper = JSONValueMapper.of(config, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -218,7 +221,7 @@ public class JSONObject extends MapWrapper<String, JSON> implements JSON, JSONGe
|
||||
* @throws JSONException 值是无穷数字抛出此异常
|
||||
*/
|
||||
public JSONObject set(final String key, final Object value) throws JSONException {
|
||||
this.put(key, this.config.getConverter().convert(JSON.class, value));
|
||||
this.put(key, this.mapper.map(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,10 @@ package org.dromara.hutool.json;
|
||||
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.lang.wrapper.Wrapper;
|
||||
import org.dromara.hutool.core.math.NumberUtil;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
import org.dromara.hutool.json.writer.ValueWriter;
|
||||
import org.dromara.hutool.json.writer.ValueWriterManager;
|
||||
import org.dromara.hutool.json.writer.NumberWriteMode;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
@ -40,6 +39,21 @@ import java.math.BigInteger;
|
||||
public class JSONPrimitive implements Wrapper<Object>, JSON {
|
||||
private static final long serialVersionUID = -2026215279191790345L;
|
||||
|
||||
/**
|
||||
* JS中表示的数字最大值
|
||||
*/
|
||||
private static final long JS_MAX_NUMBER = 9007199254740992L;
|
||||
|
||||
/**
|
||||
* 判断给定对象是否可以转为JSONPrimitive类型
|
||||
*
|
||||
* @param value 值
|
||||
* @return 是否为JSONPrimitive类型
|
||||
*/
|
||||
public static boolean isTypeForJSONPrimitive(final Object value) {
|
||||
return value instanceof Boolean || value instanceof Number || value instanceof String;
|
||||
}
|
||||
|
||||
private Object value;
|
||||
/**
|
||||
* 配置项
|
||||
@ -161,22 +175,18 @@ public class JSONPrimitive implements Wrapper<Object>, JSON {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T convert(final Type targetType, final Object value, final T defaultValue) {
|
||||
return JSON.super.convert(targetType, this.value, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final JSONWriter writer) throws JSONException {
|
||||
// 自定义规则
|
||||
final ValueWriter valueWriter = ValueWriterManager.getInstance().get(value);
|
||||
if (null != valueWriter) {
|
||||
valueWriter.write(writer, value);
|
||||
return;
|
||||
if(value instanceof Boolean){
|
||||
// Boolean
|
||||
writer.writeRaw(value.toString());
|
||||
} else if (value instanceof Number){
|
||||
// Number
|
||||
writeNumber(writer, (Number) value);
|
||||
} else{
|
||||
// 默认包装字符串
|
||||
writer.writeQuoteStrValue(value.toString());
|
||||
}
|
||||
|
||||
// 默认包装字符串
|
||||
writer.writeQuoteStrValue(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -185,4 +195,36 @@ public class JSONPrimitive implements Wrapper<Object>, JSON {
|
||||
write(jsonWriter);
|
||||
return jsonWriter.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 写出数字,根据{@link JSONConfig#isStripTrailingZeros()} 配置不同,写出不同数字<br>
|
||||
* 主要针对Double型是否去掉小数点后多余的0<br>
|
||||
* 此方法输出的值不包装引号。
|
||||
*
|
||||
* @param writer {@link JSONWriter}
|
||||
* @param number 数字
|
||||
*/
|
||||
private void writeNumber(final JSONWriter writer, final Number number) {
|
||||
final JSONConfig config = writer.getConfig();
|
||||
// since 5.6.2可配置是否去除末尾多余0,例如如果为true,5.0返回5
|
||||
final boolean isStripTrailingZeros = (null == config) || config.isStripTrailingZeros();
|
||||
final String numberStr = NumberUtil.toStr(number, isStripTrailingZeros);
|
||||
|
||||
final NumberWriteMode numberWriteMode = (null == config) ? NumberWriteMode.NORMAL : config.getNumberWriteMode();
|
||||
switch (numberWriteMode){
|
||||
case JS:
|
||||
if(number.longValue() > JS_MAX_NUMBER){
|
||||
writer.writeQuoteStrValue(numberStr);
|
||||
} else{
|
||||
writer.writeRaw(numberStr);
|
||||
}
|
||||
break;
|
||||
case STRING:
|
||||
writer.writeQuoteStrValue(numberStr);
|
||||
break;
|
||||
default:
|
||||
writer.writeRaw(numberStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,12 +25,9 @@ import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.mapper.JSONValueMapper;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
import org.dromara.hutool.json.writer.ValueWriter;
|
||||
import org.dromara.hutool.json.writer.ValueWriterManager;
|
||||
import org.dromara.hutool.json.xml.JSONXMLUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
@ -301,16 +298,6 @@ public class JSONUtil {
|
||||
* @since 5.7.12
|
||||
*/
|
||||
public static String toJsonStr(final Object obj, final JSONConfig jsonConfig) {
|
||||
// 自定义规则,优先级高于全局规则
|
||||
final ValueWriter valueWriter = ValueWriterManager.getInstance().get(obj);
|
||||
if (null != valueWriter) {
|
||||
final StringWriter stringWriter = new StringWriter();
|
||||
final JSONWriter jsonWriter = JSONWriter.of(stringWriter, 0, 0, null);
|
||||
// 用户对象自定义实现了JSONValueWriter接口,理解为需要自定义输出
|
||||
valueWriter.write(jsonWriter, obj);
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
if (null == obj) {
|
||||
return null;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import org.dromara.hutool.json.mapper.JSONValueMapper;
|
||||
import org.dromara.hutool.json.reader.JSONParser;
|
||||
import org.dromara.hutool.json.reader.JSONTokener;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.SerializerManager;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
@ -181,7 +181,7 @@ public class JSONConverter implements Converter, Serializable {
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T toBean(final Type targetType, final JSON json) {
|
||||
// 自定义对象反序列化
|
||||
final JSONDeserializer<?> deserializer = SerializerManager.getInstance().getDeserializer(json, targetType);
|
||||
final JSONDeserializer<?> deserializer = TypeAdapterManager.getInstance().getDeserializer(json, targetType);
|
||||
if (null != deserializer) {
|
||||
return (T) deserializer.deserialize(json, targetType);
|
||||
}
|
||||
|
@ -17,18 +17,17 @@
|
||||
package org.dromara.hutool.json.mapper;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.exception.ExceptionUtil;
|
||||
import org.dromara.hutool.core.lang.Opt;
|
||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||
import org.dromara.hutool.core.map.MapWrapper;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.*;
|
||||
import org.dromara.hutool.json.reader.JSONParser;
|
||||
import org.dromara.hutool.json.reader.JSONTokener;
|
||||
import org.dromara.hutool.json.serializer.JSONSerializer;
|
||||
import org.dromara.hutool.json.serializer.SerializerManager;
|
||||
import org.dromara.hutool.json.serializer.SimpleJSONContext;
|
||||
import org.dromara.hutool.json.writer.ValueWriterManager;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
import org.dromara.hutool.json.xml.JSONXMLParser;
|
||||
import org.dromara.hutool.json.xml.ParseConfig;
|
||||
|
||||
@ -78,7 +77,7 @@ public class JSONValueMapper implements Serializable {
|
||||
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@link Predicate#test(Object)}为{@code true}保留
|
||||
*/
|
||||
public JSONValueMapper(final JSONConfig jsonConfig, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
this.jsonConfig = jsonConfig;
|
||||
this.jsonConfig = ObjUtil.defaultIfNull(jsonConfig, JSONConfig::of);
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
@ -154,13 +153,14 @@ public class JSONValueMapper implements Serializable {
|
||||
}
|
||||
|
||||
// 自定义序列化
|
||||
final JSONSerializer<Object> serializer = SerializerManager.getInstance().getSerializer(obj);
|
||||
final JSONSerializer<Object> serializer = TypeAdapterManager.getInstance()
|
||||
.getSerializer(obj, obj.getClass());
|
||||
if (null != serializer) {
|
||||
return serializer.serialize(obj, new SimpleJSONContext(null, this.jsonConfig));
|
||||
}
|
||||
|
||||
// 原始类型
|
||||
if (null != ValueWriterManager.getInstance().get(obj)) {
|
||||
if (JSONPrimitive.isTypeForJSONPrimitive(obj)) {
|
||||
return new JSONPrimitive(obj, jsonConfig);
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ public class JSONValueMapper implements Serializable {
|
||||
if (jsonConfig.isIgnoreError()) {
|
||||
return null;
|
||||
}
|
||||
throw ExceptionUtil.wrap(exception, JSONException.class);
|
||||
throw exception instanceof JSONException ? (JSONException) exception : new JSONException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.dromara.hutool.json.serializer;
|
||||
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONConfig;
|
||||
|
||||
@ -40,6 +41,6 @@ public interface JSONContext {
|
||||
* @return JSON配置
|
||||
*/
|
||||
default JSONConfig config() {
|
||||
return getContextJson().config();
|
||||
return ObjUtil.apply(getContextJson(), JSON::config);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import java.lang.reflect.Type;
|
||||
* @author Looly
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface JSONDeserializer<V> {
|
||||
public interface JSONDeserializer<V> extends TypeAdapter{
|
||||
|
||||
/**
|
||||
* 反序列化,通过实现此方法,自定义实现JSON转换为指定类型的逻辑<br>
|
||||
|
@ -27,7 +27,7 @@ import org.dromara.hutool.json.JSONObject;
|
||||
* @author Looly
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface JSONSerializer<V> {
|
||||
public interface JSONSerializer<V> extends TypeAdapter{
|
||||
|
||||
/**
|
||||
* 序列化实现,通过实现此方法,将指定类型的对象转换为{@link JSON}对象,可以:
|
||||
|
@ -14,9 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.serializer;
|
||||
|
||||
/**
|
||||
* {@link org.dromara.hutool.json.writer.ValueWriter} 实现
|
||||
* JSON类型适配器,实现此接口即同时实现对象的序列化和反序列化
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
package org.dromara.hutool.json.writer.impl;
|
||||
public interface TypeAdapter{}
|
@ -19,39 +19,37 @@ package org.dromara.hutool.json.serializer;
|
||||
import org.dromara.hutool.core.collection.CollUtil;
|
||||
import org.dromara.hutool.core.collection.set.ConcurrentHashSet;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONException;
|
||||
import org.dromara.hutool.json.serializer.impl.*;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* JSON序列化和反序列化管理器,用于管理JSON序列化器,注册和注销自定义序列化器和反序列化器。<br>
|
||||
* 此管理器管理着两种类型的序列化器和反序列化器:
|
||||
* <ul>
|
||||
* <li>类型精准匹配方式。通过Java对象类型匹配,只会匹配查找的类型,而不匹配子类。可以调用{@link #register(Type, JSONSerializer)} 和 {@link #register(Type, JSONDeserializer)}注册。</li>
|
||||
* <li>匹配器(Matcher)方式。通过判断序列化和反序列化器中match方法,找到自定义的序列化和反序列化器,可以调用{@link #register(MatcherJSONSerializer)} 和 {@link #register(MatcherJSONDeserializer)}注册。</li>
|
||||
* <li>类型精准匹配方式。通过Java对象类型匹配,只会匹配查找的类型,而不匹配子类。可以调用{@link #register(Type, TypeAdapter)}注册。</li>
|
||||
* <li>匹配器(Matcher)方式。通过判断序列化和反序列化器中match方法,找到自定义的序列化和反序列化器,可以调用{@link #register(TypeAdapter)}注册。</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* 管理器的使用分为三种方式:
|
||||
* <ul>
|
||||
* <li>全局模式: 使用{@link SerializerManager#getInstance()}调用单例,全局可用。</li>
|
||||
* <li>实例模式: 使用{@link SerializerManager#of()}创建实例,局部可用。</li>
|
||||
* <li>全局模式: 使用{@link TypeAdapterManager#getInstance()}调用单例,全局可用。</li>
|
||||
* <li>实例模式: 使用{@link TypeAdapterManager#of()}创建实例,局部可用。</li>
|
||||
* <li>自定义模式:使用{@code new SerializerManager()}创建实例,不加载默认的转换器。</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class SerializerManager {
|
||||
public class TypeAdapterManager {
|
||||
/**
|
||||
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
|
||||
*/
|
||||
@ -59,7 +57,8 @@ public class SerializerManager {
|
||||
/**
|
||||
* 静态初始化器,由JVM来保证线程安全
|
||||
*/
|
||||
private static final SerializerManager INSTANCE = new SerializerManager();
|
||||
private static final TypeAdapterManager INSTANCE = new TypeAdapterManager();
|
||||
|
||||
static {
|
||||
registerDefault(INSTANCE);
|
||||
}
|
||||
@ -70,8 +69,8 @@ public class SerializerManager {
|
||||
*
|
||||
* @return SerializerManager
|
||||
*/
|
||||
public static SerializerManager getInstance() {
|
||||
return SerializerManager.SingletonHolder.INSTANCE;
|
||||
public static TypeAdapterManager getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,10 +78,10 @@ public class SerializerManager {
|
||||
*
|
||||
* @return SerializerManager
|
||||
*/
|
||||
public static SerializerManager of() {
|
||||
final SerializerManager serializerManager = new SerializerManager();
|
||||
registerDefault(serializerManager);
|
||||
return serializerManager;
|
||||
public static TypeAdapterManager of() {
|
||||
final TypeAdapterManager typeAdapterManager = new TypeAdapterManager();
|
||||
registerDefault(typeAdapterManager);
|
||||
return typeAdapterManager;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,73 +106,54 @@ public class SerializerManager {
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public SerializerManager() {
|
||||
public TypeAdapterManager() {
|
||||
}
|
||||
|
||||
// region ----- register
|
||||
|
||||
/**
|
||||
* 注册自定义序列化器,用于自定义对象序列化<br>
|
||||
* 当按照匹配规则匹配时,使用对应的序列化器进行序列化
|
||||
* 注册自定义类型适配器,用于自定义对象序列化和反序列化<br>
|
||||
* 提供的适配器必须为实现{@link MatcherJSONSerializer}或{@link MatcherJSONDeserializer}接口<br>
|
||||
* 当两个接口都实现时,同时注册序列化和反序列化器
|
||||
*
|
||||
* @param serializer 自定义序列化器
|
||||
* @param typeAdapter 自定义类型适配器
|
||||
* @return this
|
||||
*/
|
||||
public SerializerManager register(final MatcherJSONSerializer<?> serializer) {
|
||||
if (null != serializer) {
|
||||
getSerializerSet().add(serializer);
|
||||
public TypeAdapterManager register(final TypeAdapter typeAdapter) {
|
||||
Assert.notNull(typeAdapter, "typeAdapter must be not null!");
|
||||
if(typeAdapter instanceof MatcherJSONSerializer || typeAdapter instanceof MatcherJSONDeserializer){
|
||||
if(typeAdapter instanceof MatcherJSONSerializer){
|
||||
getSerializerSet().add((MatcherJSONSerializer<?>) typeAdapter);
|
||||
}
|
||||
if(typeAdapter instanceof MatcherJSONDeserializer){
|
||||
getDeserializerSet().add((MatcherJSONDeserializer<?>) typeAdapter);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
|
||||
throw new JSONException("Adapter: {} is not MatcherJSONSerializer or MatcherJSONDeserializer", typeAdapter.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册自定义序列化器,用于自定义对象序列化<br>
|
||||
* 当类型精准匹配时,使用对应的序列化器进行序列化
|
||||
* 注册自定义类型适配器,用于自定义对象序列化和反序列化
|
||||
*
|
||||
* @param type 类型
|
||||
* @param serializer 自定义序列化器,{@code null}表示移除
|
||||
* @param typeAdapter 自定义序列化器,{@code null}表示移除
|
||||
* @return this
|
||||
*/
|
||||
public SerializerManager register(final Type type, final JSONSerializer<?> serializer) {
|
||||
public TypeAdapterManager register(final Type type, final TypeAdapter typeAdapter) {
|
||||
Assert.notNull(type);
|
||||
if (null == serializer) {
|
||||
getSerializerMap().remove(type);
|
||||
} else {
|
||||
getSerializerMap().put(type, serializer);
|
||||
if(typeAdapter instanceof JSONSerializer || typeAdapter instanceof JSONDeserializer){
|
||||
if(typeAdapter instanceof JSONSerializer){
|
||||
getSerializerMap().put(type, (JSONSerializer<?>) typeAdapter);
|
||||
}
|
||||
if(typeAdapter instanceof JSONDeserializer){
|
||||
getDeserializerMap().put(type, (JSONDeserializer<?>) typeAdapter);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册自定义反序列化器,用于自定义对象反序列化<br>
|
||||
* 当按照匹配规则匹配时,使用对应的反序列化器进行反序列化
|
||||
*
|
||||
* @param deserializer 自定义反序列化器
|
||||
* @return this
|
||||
*/
|
||||
public SerializerManager register(final MatcherJSONDeserializer<?> deserializer) {
|
||||
if (null != deserializer) {
|
||||
getDeserializerSet().add(deserializer);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册自定义反序列化器,用于自定义对象反序列化<br>
|
||||
* 当类型精准匹配时,使用对应的反序列化器进行反序列化
|
||||
*
|
||||
* @param type 类型,{@code null}表示
|
||||
* @param deserializer 自定义反序列化器,{@code null}表示移除
|
||||
* @return this
|
||||
*/
|
||||
public SerializerManager register(final Type type, final JSONDeserializer<?> deserializer) {
|
||||
Assert.notNull(type);
|
||||
if (null == deserializer) {
|
||||
getDeserializerMap().remove(type);
|
||||
} else {
|
||||
getDeserializerMap().put(type, deserializer);
|
||||
}
|
||||
return this;
|
||||
throw new JSONException("Adapter: {} is not JSONSerializer or JSONDeserializer", typeAdapter.getClass());
|
||||
}
|
||||
// endregion
|
||||
|
||||
@ -183,60 +163,53 @@ public class SerializerManager {
|
||||
* 获取匹配器对应的序列化器
|
||||
*
|
||||
* @param bean 对象
|
||||
* @return JSONSerializer
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public MatcherJSONSerializer<Object> getSerializer(final Object bean) {
|
||||
if(CollUtil.isNotEmpty(this.serializerSet)){
|
||||
for (final MatcherJSONSerializer<?> serializer : this.serializerSet) {
|
||||
if (serializer.match(bean, null)) {
|
||||
return (MatcherJSONSerializer<Object>) serializer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取匹配器对应的序列化器
|
||||
*
|
||||
* @param type 类型
|
||||
* @return JSONSerializer
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public JSONSerializer<Object> getSerializer(final Type type) {
|
||||
if(null == type || CollUtil.isEmpty(this.serializerMap)){
|
||||
return null;
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public JSONSerializer<Object> getSerializer(final Object bean, final Type type) {
|
||||
JSONSerializer<Object> result = null;
|
||||
if (null != type && MapUtil.isNotEmpty(this.serializerMap)) {
|
||||
result = (JSONSerializer<Object>) this.serializerMap.get(type);
|
||||
}
|
||||
return (JSONSerializer<Object>) this.serializerMap.get(type);
|
||||
|
||||
if (null == result && CollUtil.isNotEmpty(this.serializerSet)) {
|
||||
for (final MatcherJSONSerializer<?> serializer : this.serializerSet) {
|
||||
if (serializer.match(bean, null)) {
|
||||
result = (MatcherJSONSerializer<Object>) serializer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取匹配器对应的反序列化器
|
||||
*
|
||||
* @param json JSON
|
||||
* @param type 类型
|
||||
* @return JSONDeserializer
|
||||
* @param json JSON, 单独查找强类型匹配传{@code null}
|
||||
* @param type 类型, 单独查匹配器传{@code null}
|
||||
* @return JSONDeserializer,始终非空
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public JSONDeserializer<Object> getDeserializer(final JSON json, final Type type) {
|
||||
final Class<?> rawType = TypeUtil.getClass(type);
|
||||
if(null == rawType){
|
||||
if (null == rawType) {
|
||||
return null;
|
||||
}
|
||||
if (JSONDeserializer.class.isAssignableFrom(rawType)) {
|
||||
return (JSONDeserializer<Object>) ConstructorUtil.newInstanceIfPossible(rawType);
|
||||
}
|
||||
|
||||
if(CollUtil.isNotEmpty(this.deserializerMap)){
|
||||
if (CollUtil.isNotEmpty(this.deserializerMap)) {
|
||||
final JSONDeserializer<?> jsonDeserializer = this.deserializerMap.get(type);
|
||||
if(null != jsonDeserializer){
|
||||
if (null != jsonDeserializer) {
|
||||
return (JSONDeserializer<Object>) jsonDeserializer;
|
||||
}
|
||||
}
|
||||
|
||||
// Matcher
|
||||
if(CollUtil.isNotEmpty(this.deserializerSet)){
|
||||
if (CollUtil.isNotEmpty(this.deserializerSet)) {
|
||||
for (final MatcherJSONDeserializer<?> deserializer : this.deserializerSet) {
|
||||
if (deserializer.match(json, type)) {
|
||||
return (JSONDeserializer<Object>) deserializer;
|
||||
@ -244,7 +217,7 @@ public class SerializerManager {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return DefaultDeserializer.INSTANCE;
|
||||
}
|
||||
// endregion
|
||||
|
||||
@ -292,32 +265,30 @@ public class SerializerManager {
|
||||
}
|
||||
return this.deserializerMap;
|
||||
}
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* 注册默认的序列化器和反序列化器
|
||||
*
|
||||
* @param manager {@code SerializerManager}
|
||||
*/
|
||||
private static void registerDefault(final SerializerManager manager) {
|
||||
manager.register(LocalDate.class, (JSONSerializer<?>) new TemporalAccessorSerializer(LocalDate.class));
|
||||
manager.register(LocalDate.class, (JSONDeserializer<?>) new TemporalAccessorSerializer(LocalDate.class));
|
||||
|
||||
manager.register(LocalTime.class, (JSONSerializer<?>) new TemporalAccessorSerializer(LocalTime.class));
|
||||
manager.register(LocalTime.class, (JSONDeserializer<?>) new TemporalAccessorSerializer(LocalTime.class));
|
||||
|
||||
manager.register(LocalDateTime.class, (JSONSerializer<?>) new TemporalAccessorSerializer(LocalDateTime.class));
|
||||
manager.register(LocalDateTime.class, (JSONDeserializer<?>) new TemporalAccessorSerializer(LocalDateTime.class));
|
||||
|
||||
manager.register((MatcherJSONSerializer<TimeZone>) TimeZoneSerializer.INSTANCE);
|
||||
manager.register((MatcherJSONDeserializer<TimeZone>) TimeZoneSerializer.INSTANCE);
|
||||
|
||||
private static void registerDefault(final TypeAdapterManager manager) {
|
||||
// issue#I5WDP0 对于Kotlin对象,由于参数可能非空限制,导致无法创建一个默认的对象再赋值
|
||||
manager.register(KBeanDeserializer.INSTANCE);
|
||||
|
||||
manager.register(CollectionDeserializer.INSTANCE);
|
||||
manager.register(ArrayDeserializer.INSTANCE);
|
||||
manager.register(MapDeserializer.INSTANCE);
|
||||
manager.register(EntryDeserializer.INSTANCE);
|
||||
manager.register(RecordDeserializer.INSTANCE);
|
||||
|
||||
|
||||
manager.register(DateTypeAdapter.INSTANCE);
|
||||
manager.register(CalendarTypeAdapter.INSTANCE);
|
||||
manager.register(TemporalTypeAdapter.INSTANCE);
|
||||
manager.register(TimeZoneTypeAdapter.INSTANCE);
|
||||
manager.register(EnumTypeAdapter.INSTANCE);
|
||||
manager.register(ThrowableTypeAdapter.INSTANCE);
|
||||
// 最低优先级
|
||||
manager.register(BeanTypeAdapter.INSTANCE);
|
||||
}
|
||||
// endregion
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.bean.BeanUtil;
|
||||
import org.dromara.hutool.core.bean.copier.BeanToMapCopier;
|
||||
import org.dromara.hutool.core.bean.copier.ValueProviderToBeanCopier;
|
||||
import org.dromara.hutool.core.lang.copier.Copier;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.InternalJSONUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONObject;
|
||||
import org.dromara.hutool.json.serializer.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Bean对象适配器,将Bean对象序列化为JSONObject,反序列化为Bean对象
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class BeanTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJSONDeserializer<Object> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final BeanTypeAdapter INSTANCE = new BeanTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
final JSON contextJson = ObjUtil.apply(context, JSONContext::getContextJson);
|
||||
return BeanUtil.isReadableBean(bean.getClass())
|
||||
&& (null == contextJson || contextJson instanceof JSONObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
return json instanceof JSONObject && BeanUtil.isWritableBean(TypeUtil.getClass(deserializeType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON serialize(final Object bean, final JSONContext context) {
|
||||
JSONObject contextJson = (JSONObject) ObjUtil.apply(context, JSONContext::getContextJson);
|
||||
if(null == contextJson){
|
||||
contextJson = new JSONObject(context.config());
|
||||
}
|
||||
|
||||
final BeanToMapCopier copier = new BeanToMapCopier(
|
||||
bean,
|
||||
contextJson,
|
||||
JSONObject.class, InternalJSONUtil.toCopyOptions(context.config())
|
||||
);
|
||||
return (JSON) copier.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
final Copier<Object> copier = new ValueProviderToBeanCopier<>(
|
||||
new JSONObjectValueProvider((JSONObject) json),
|
||||
ConstructorUtil.newInstanceIfPossible(TypeUtil.getClass(deserializeType)),
|
||||
deserializeType,
|
||||
InternalJSONUtil.toCopyOptions(json.config())
|
||||
);
|
||||
return copier.copy();
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.impl.CalendarConverter;
|
||||
import org.dromara.hutool.core.date.DateUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONConfig;
|
||||
import org.dromara.hutool.json.JSONPrimitive;
|
||||
import org.dromara.hutool.json.serializer.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* 日期类型适配器,用于将日期对象转换为给定格式或时间戳
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class CalendarTypeAdapter implements MatcherJSONSerializer<Calendar>, MatcherJSONDeserializer<Calendar> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final CalendarTypeAdapter INSTANCE = new CalendarTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return bean instanceof Calendar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
return Calendar.class.isAssignableFrom(TypeUtil.getClass(deserializeType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON serialize(final Calendar bean, final JSONContext context) {
|
||||
final JSONConfig config = ObjUtil.apply(context, JSONContext::config);
|
||||
final String format = ObjUtil.apply(config, JSONConfig::getDateFormat);
|
||||
return new JSONPrimitive(
|
||||
null == format
|
||||
? bean.getTimeInMillis()
|
||||
: DateUtil.format(DateUtil.date(bean), format), config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Calendar deserialize(final JSON json, final Type deserializeType) {
|
||||
final JSONConfig config = json.config();
|
||||
final String format = ObjUtil.apply(config, JSONConfig::getDateFormat);
|
||||
return (Calendar) new CalendarConverter(format).convert(deserializeType, json.asJSONPrimitive().getValue());
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.impl.DateConverter;
|
||||
import org.dromara.hutool.core.date.DateUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONConfig;
|
||||
import org.dromara.hutool.json.JSONPrimitive;
|
||||
import org.dromara.hutool.json.serializer.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 日期类型适配器,用于将日期对象转换为给定格式或时间戳
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class DateTypeAdapter implements MatcherJSONSerializer<Date>, MatcherJSONDeserializer<Date> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final DateTypeAdapter INSTANCE = new DateTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return bean instanceof Date;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
return Date.class.isAssignableFrom(TypeUtil.getClass(deserializeType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON serialize(final Date bean, final JSONContext context) {
|
||||
final JSONConfig config = ObjUtil.apply(context, JSONContext::config);
|
||||
final String format = ObjUtil.apply(config, JSONConfig::getDateFormat);
|
||||
return new JSONPrimitive(
|
||||
null == format
|
||||
? bean.getTime()
|
||||
: DateUtil.format(bean, format), config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date deserialize(final JSON json, final Type deserializeType) {
|
||||
final JSONConfig config = json.config();
|
||||
final String format = ObjUtil.apply(config, JSONConfig::getDateFormat);
|
||||
return (Date) new DateConverter(format).convert(deserializeType, json.asJSONPrimitive().getValue());
|
||||
}
|
||||
}
|
@ -16,14 +16,10 @@
|
||||
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.bean.copier.ValueProviderToBeanCopier;
|
||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
||||
import org.dromara.hutool.core.lang.copier.Copier;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.json.*;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.JSONObjectValueProvider;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
@ -34,6 +30,12 @@ import java.lang.reflect.Type;
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class DefaultDeserializer implements JSONDeserializer<Object> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final DefaultDeserializer INSTANCE = new DefaultDeserializer();
|
||||
|
||||
@Override
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
// 当目标类型不确定时,返回原JSON
|
||||
@ -61,14 +63,7 @@ public class DefaultDeserializer implements JSONDeserializer<Object> {
|
||||
* @return 反序列化后的对象
|
||||
*/
|
||||
private Object fromJSONObject(final JSONObject json, final Type deserializeType, final Class<?> rawType) {
|
||||
// 转为POJO
|
||||
final Copier<Object> copier = new ValueProviderToBeanCopier<>(
|
||||
new JSONObjectValueProvider(json),
|
||||
ConstructorUtil.newInstanceIfPossible(rawType),
|
||||
deserializeType,
|
||||
InternalJSONUtil.toCopyOptions(json.config())
|
||||
);
|
||||
return copier.copy();
|
||||
throw new JSONException("Unsupported JSONObject to {}", rawType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,7 +75,7 @@ public class DefaultDeserializer implements JSONDeserializer<Object> {
|
||||
* @return 反序列化后的对象
|
||||
*/
|
||||
private Object fromJSONArray(final JSONArray json, final Type deserializeType, final Class<?> rawType) {
|
||||
return json;
|
||||
throw new JSONException("Unsupported JSONArray to {}", rawType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.util.EnumUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONPrimitive;
|
||||
import org.dromara.hutool.json.serializer.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 枚举类型适配器,将枚举转换为字符串,反序列化时将字符串转为枚举对象
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class EnumTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJSONDeserializer<Object> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final EnumTypeAdapter INSTANCE = new EnumTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return EnumUtil.isEnum(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
return EnumUtil.isEnum(deserializeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON serialize(final Object bean, final JSONContext context) {
|
||||
return new JSONPrimitive(((Enum<?>) bean).name(),
|
||||
ObjUtil.apply(context, JSONContext::config));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@Override
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
return EnumUtil.fromString((Class) TypeUtil.getClass(deserializeType), (String) json.asJSONPrimitive().getValue());
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.serializer;
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.bean.copier.ValueProvider;
|
||||
import org.dromara.hutool.json.JSON;
|
@ -20,7 +20,6 @@ import org.dromara.hutool.core.bean.RecordUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONObject;
|
||||
import org.dromara.hutool.json.serializer.JSONObjectValueProvider;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
@ -20,10 +20,11 @@ import org.dromara.hutool.core.convert.impl.TemporalAccessorConverter;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.lang.Opt;
|
||||
import org.dromara.hutool.core.math.NumberUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.json.*;
|
||||
import org.dromara.hutool.json.serializer.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.JSONSerializer;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.LocalDate;
|
||||
@ -41,9 +42,8 @@ import java.time.temporal.TemporalAccessor;
|
||||
* </ul>
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.22
|
||||
*/
|
||||
public class TemporalAccessorSerializer implements JSONSerializer<TemporalAccessor>, JSONDeserializer<TemporalAccessor> {
|
||||
public class TemporalTypeAdapter implements MatcherJSONSerializer<TemporalAccessor>, MatcherJSONDeserializer<TemporalAccessor> {
|
||||
|
||||
private static final String YEAR_KEY = "year";
|
||||
private static final String MONTH_KEY = "month";
|
||||
@ -53,15 +53,19 @@ public class TemporalAccessorSerializer implements JSONSerializer<TemporalAccess
|
||||
private static final String SECOND_KEY = "second";
|
||||
private static final String NANO_KEY = "nano";
|
||||
|
||||
private final Class<? extends TemporalAccessor> temporalAccessorClass;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param temporalAccessorClass TemporalAccessor实现类型
|
||||
* 单例
|
||||
*/
|
||||
public TemporalAccessorSerializer(final Class<? extends TemporalAccessor> temporalAccessorClass) {
|
||||
this.temporalAccessorClass = temporalAccessorClass;
|
||||
public static final TemporalTypeAdapter INSTANCE = new TemporalTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
return TemporalAccessor.class.isAssignableFrom(TypeUtil.getClass(deserializeType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return bean instanceof TemporalAccessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -111,9 +115,10 @@ public class TemporalAccessorSerializer implements JSONSerializer<TemporalAccess
|
||||
|
||||
// TODO JSONArray
|
||||
|
||||
final Class<?> temporalAccessorClass = TypeUtil.getClass(deserializeType);
|
||||
// JSONObject
|
||||
final JSONObject jsonObject = (JSONObject) json;
|
||||
if (LocalDate.class.equals(this.temporalAccessorClass) || LocalDateTime.class.equals(this.temporalAccessorClass)) {
|
||||
if (LocalDate.class.equals(temporalAccessorClass) || LocalDateTime.class.equals(temporalAccessorClass)) {
|
||||
// 年
|
||||
final Integer year = jsonObject.getInt(YEAR_KEY);
|
||||
Assert.notNull(year, "Field 'year' must be not null");
|
||||
@ -135,7 +140,7 @@ public class TemporalAccessorSerializer implements JSONSerializer<TemporalAccess
|
||||
}
|
||||
|
||||
final LocalDate localDate = LocalDate.of(year, month, day);
|
||||
if (LocalDate.class.equals(this.temporalAccessorClass)) {
|
||||
if (LocalDate.class.equals(temporalAccessorClass)) {
|
||||
return localDate;
|
||||
}
|
||||
|
||||
@ -147,7 +152,7 @@ public class TemporalAccessorSerializer implements JSONSerializer<TemporalAccess
|
||||
jsonObject.getInt(NANO_KEY, 0));
|
||||
|
||||
return LocalDateTime.of(localDate, localTime);
|
||||
} else if (LocalTime.class.equals(this.temporalAccessorClass)) {
|
||||
} else if (LocalTime.class.equals(temporalAccessorClass)) {
|
||||
return LocalTime.of(
|
||||
jsonObject.getInt(HOUR_KEY),
|
||||
jsonObject.getInt(MINUTE_KEY),
|
||||
@ -155,6 +160,6 @@ public class TemporalAccessorSerializer implements JSONSerializer<TemporalAccess
|
||||
jsonObject.getInt(NANO_KEY));
|
||||
}
|
||||
|
||||
throw new JSONException("Unsupported type from JSON: {}", this.temporalAccessorClass);
|
||||
throw new JSONException("Unsupported type from JSON: {}", deserializeType);
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONPrimitive;
|
||||
import org.dromara.hutool.json.serializer.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Throwable类型适配器,用于将Throwable对象转换为JSON对象
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class ThrowableTypeAdapter implements MatcherJSONSerializer<Throwable>, MatcherJSONDeserializer<Throwable> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final ThrowableTypeAdapter INSTANCE = new ThrowableTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return bean instanceof Throwable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
return Throwable.class.isAssignableFrom(TypeUtil.getClass(deserializeType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON serialize(final Throwable bean, final JSONContext context) {
|
||||
return new JSONPrimitive(
|
||||
StrUtil.format("{}: {}", bean.getClass().getName(), bean.getMessage()),
|
||||
ObjUtil.apply(context, JSONContext::config));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable deserialize(final JSON json, final Type deserializeType) {
|
||||
final String value = (String) json.asJSONPrimitive().getValue();
|
||||
return (Throwable) ConstructorUtil.newInstance(TypeUtil.getClass(deserializeType),
|
||||
StrUtil.subAfter(value, ": ", false));
|
||||
}
|
||||
}
|
@ -27,17 +27,17 @@ import java.lang.reflect.Type;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* 时区序列化器
|
||||
* 时区类型适配器
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class TimeZoneSerializer implements MatcherJSONSerializer<TimeZone>, MatcherJSONDeserializer<TimeZone> {
|
||||
public class TimeZoneTypeAdapter implements MatcherJSONSerializer<TimeZone>, MatcherJSONDeserializer<TimeZone> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final TimeZoneSerializer INSTANCE = new TimeZoneSerializer();
|
||||
public static final TimeZoneTypeAdapter INSTANCE = new TimeZoneTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
@ -27,5 +27,16 @@
|
||||
* <li>序列化(Serialize) 指:【Java对象】 转换为 【JSON对象】</li>
|
||||
* <li>反序列化(Deserialize)指:【JSON对象】 转换为 【Java对象】</li>
|
||||
* </ul>
|
||||
*
|
||||
* 3. JSON序列化实现:
|
||||
* <ul>
|
||||
* <li>TypeAdapter:类型适配器,标记序列化或反序列化</li>
|
||||
* <li>JSONSerializer:JSON序列化接口,用于自定义序列化</li>
|
||||
* <li>JSONDeserializer:JSON反序列化接口,用于自定义反序列化</li>
|
||||
* </ul>
|
||||
*
|
||||
* 4. JSON序列化管理:<br>
|
||||
* TypeAdapterManager用于管理定义的序列化和反序列化器
|
||||
*
|
||||
*/
|
||||
package org.dromara.hutool.json.serializer;
|
||||
|
@ -372,13 +372,6 @@ public class JSONWriter implements Appendable, Flushable, Closeable {
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
private JSONWriter writeObjValue(final Object value) {
|
||||
// 自定义规则
|
||||
final ValueWriter valueWriter = ValueWriterManager.getInstance().get(value);
|
||||
if (null != valueWriter) {
|
||||
valueWriter.write(this, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
// 默认规则
|
||||
if (value == null) {
|
||||
writeRaw(StrUtil.NULL);
|
||||
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.writer;
|
||||
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.json.writer.impl.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ValueWriter管理器,用于管理ValueWriter,提供ValueWriter的注册和获取
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.8.0
|
||||
*/
|
||||
public class ValueWriterManager {
|
||||
|
||||
/**
|
||||
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
|
||||
*/
|
||||
private static class SingletonHolder {
|
||||
/**
|
||||
* 静态初始化器,由JVM来保证线程安全
|
||||
*/
|
||||
private static final ValueWriterManager INSTANCE;
|
||||
static {
|
||||
INSTANCE = new ValueWriterManager();
|
||||
registerDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得单例的 ValueWriterManager
|
||||
*
|
||||
* @return ValueWriterManager
|
||||
*/
|
||||
public static ValueWriterManager getInstance() {
|
||||
return ValueWriterManager.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private final List<ValueWriter> valueWriterList;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public ValueWriterManager() {
|
||||
this.valueWriterList = Collections.synchronizedList(new ArrayList<>(6));
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入自定义的对象值写出规则
|
||||
*
|
||||
* @param valueWriter 自定义对象写出实现
|
||||
*/
|
||||
public void register(final ValueWriter valueWriter) {
|
||||
valueWriterList.add(Assert.notNull(valueWriter));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义对象值写出规则,后加入的优先
|
||||
*
|
||||
* @param value 值,{@code null}表示需要自定义null的输出
|
||||
* @return 自定义的 {@link ValueWriter}
|
||||
*/
|
||||
public ValueWriter get(final Object value) {
|
||||
if (value instanceof ValueWriter) {
|
||||
return (ValueWriter) value;
|
||||
}
|
||||
|
||||
final List<ValueWriter> valueWriterList = this.valueWriterList;
|
||||
ValueWriter valueWriter;
|
||||
for (int i = valueWriterList.size() - 1 ; i >= 0 ; i--) {
|
||||
valueWriter = valueWriterList.get(i);
|
||||
if (valueWriter.test(value)) {
|
||||
return valueWriter;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册默认的ValueWriter
|
||||
*/
|
||||
private static void registerDefault() {
|
||||
final ValueWriterManager manager = SingletonHolder.INSTANCE;
|
||||
// JDK对象最后判断
|
||||
manager.register(JdkValueWriter.INSTANCE);
|
||||
manager.register(NumberValueWriter.INSTANCE);
|
||||
manager.register(DateValueWriter.INSTANCE);
|
||||
manager.register(BooleanValueWriter.INSTANCE);
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.writer.impl;
|
||||
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
import org.dromara.hutool.json.writer.ValueWriter;
|
||||
|
||||
/**
|
||||
* Boolean类型的值写出器
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class BooleanValueWriter implements ValueWriter {
|
||||
/**
|
||||
* 单例对象
|
||||
*/
|
||||
public static final BooleanValueWriter INSTANCE = new BooleanValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean test(final Object bool) {
|
||||
return bool instanceof Boolean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final JSONWriter writer, final Object bool) {
|
||||
writer.writeRaw(bool.toString());
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.writer.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
||||
import org.dromara.hutool.core.date.DateUtil;
|
||||
import org.dromara.hutool.core.date.TemporalAccessorUtil;
|
||||
import org.dromara.hutool.core.date.format.GlobalCustomFormat;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.json.InternalJSONUtil;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
import org.dromara.hutool.json.writer.ValueWriter;
|
||||
|
||||
import java.time.MonthDay;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 日期类型的值写出器<br>
|
||||
* 支持包括:{@link Date}、{@link Calendar}、{@link TemporalAccessor}
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class DateValueWriter implements ValueWriter {
|
||||
/**
|
||||
* 单例对象
|
||||
*/
|
||||
public static final DateValueWriter INSTANCE = new DateValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean test(final Object value) {
|
||||
return value instanceof Date || value instanceof Calendar || value instanceof TemporalAccessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final JSONWriter writer, final Object value) {
|
||||
final String rawString;
|
||||
// issue#2572@Github
|
||||
if (value instanceof MonthDay) {
|
||||
rawString = InternalJSONUtil.quote(value.toString());
|
||||
}else{
|
||||
rawString = formatDate(value, writer.getConfig().getDateFormat());
|
||||
}
|
||||
writer.writeRaw(rawString);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按照给定格式格式化日期,格式为空时返回时间戳字符串<br>
|
||||
* 如果给定的格式是时间戳,直接返回时间戳字符串,如果是给定字符串格式,返回带双引号包装的字符串
|
||||
*
|
||||
* @param dateObj Date或者Calendar对象
|
||||
* @param format 格式
|
||||
* @return 日期字符串
|
||||
*/
|
||||
private static String formatDate(final Object dateObj, final String format) {
|
||||
if (StrUtil.isNotBlank(format)) {
|
||||
final String dateStr;
|
||||
if (dateObj instanceof TemporalAccessor) {
|
||||
dateStr = TemporalAccessorUtil.format((TemporalAccessor) dateObj, format);
|
||||
} else {
|
||||
dateStr = DateUtil.format(ConvertUtil.toDate(dateObj), format);
|
||||
}
|
||||
|
||||
if (GlobalCustomFormat.FORMAT_SECONDS.equals(format)
|
||||
|| GlobalCustomFormat.FORMAT_MILLISECONDS.equals(format)) {
|
||||
// Hutool自定义的秒和毫秒表示,默认不包装双引号
|
||||
return dateStr;
|
||||
}
|
||||
//用户定义了日期格式
|
||||
return InternalJSONUtil.quote(dateStr);
|
||||
}
|
||||
|
||||
//默认使用时间戳
|
||||
final long timeMillis;
|
||||
if (dateObj instanceof TemporalAccessor) {
|
||||
timeMillis = TemporalAccessorUtil.toEpochMilli((TemporalAccessor) dateObj);
|
||||
} else if (dateObj instanceof Date) {
|
||||
timeMillis = ((Date) dateObj).getTime();
|
||||
} else if (dateObj instanceof Calendar) {
|
||||
timeMillis = ((Calendar) dateObj).getTimeInMillis();
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported Date type: " + dateObj.getClass());
|
||||
}
|
||||
return String.valueOf(timeMillis);
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.writer.impl;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
import org.dromara.hutool.json.writer.ValueWriter;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* JDK内置类型的值写出器
|
||||
*
|
||||
* <p>
|
||||
* 枚举类和JDK内部类直接使用toString输出,不做转换。
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* {@link SQLException}实现了Iterable导致被识别为列表,可能造成死循环,此处按照字符串处理,见:
|
||||
* https://github.com/dromara/hutool/issues/1399
|
||||
* </p>
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class JdkValueWriter implements ValueWriter {
|
||||
/**
|
||||
* 单例对象
|
||||
*/
|
||||
public static final JdkValueWriter INSTANCE = new JdkValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean test(final Object value) {
|
||||
if (null == value) {
|
||||
return false;
|
||||
}
|
||||
if (value instanceof Enum || value instanceof SQLException) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 自定义写出的跳过
|
||||
if (value instanceof Number
|
||||
|| value instanceof Date
|
||||
|| value instanceof Calendar
|
||||
|| value instanceof TemporalAccessor
|
||||
|| value instanceof Boolean
|
||||
// 可转换为JSONObject和JSONArray的对象
|
||||
|| value instanceof Map
|
||||
|| value instanceof Map.Entry
|
||||
|| value instanceof Iterable
|
||||
|| ArrayUtil.isArray(value)
|
||||
|| value instanceof Optional
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Java内部类不做转换
|
||||
return ClassUtil.isJdkClass(value.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final JSONWriter writer, final Object value) {
|
||||
final String valueStr;
|
||||
if(value instanceof Class<?>){
|
||||
valueStr = ((Class<?>) value).getName();
|
||||
}else{
|
||||
valueStr = value.toString();
|
||||
}
|
||||
writer.writeQuoteStrValue(valueStr);
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.writer.impl;
|
||||
|
||||
import org.dromara.hutool.core.math.NumberUtil;
|
||||
import org.dromara.hutool.json.JSONConfig;
|
||||
import org.dromara.hutool.json.JSONException;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
import org.dromara.hutool.json.writer.NumberWriteMode;
|
||||
import org.dromara.hutool.json.writer.ValueWriter;
|
||||
|
||||
/**
|
||||
* 数字类型的值写出器
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class NumberValueWriter implements ValueWriter {
|
||||
|
||||
/**
|
||||
* JS中表示的数字最大值
|
||||
*/
|
||||
private static final long JS_MAX_NUMBER = 9007199254740992L;
|
||||
|
||||
/**
|
||||
* 单例对象
|
||||
*/
|
||||
public static final NumberValueWriter INSTANCE = new NumberValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean test(final Object value) {
|
||||
// 合法数字原样存储
|
||||
if(value instanceof Number){
|
||||
if(!NumberUtil.isValidNumber((Number) value)){
|
||||
throw new JSONException("JSON does not allow non-finite numbers.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写出数字,根据{@link JSONConfig#isStripTrailingZeros()} 配置不同,写出不同数字<br>
|
||||
* 主要针对Double型是否去掉小数点后多余的0<br>
|
||||
* 此方法输出的值不包装引号。
|
||||
*
|
||||
* @param writer {@link JSONWriter}
|
||||
* @param value 数字
|
||||
*/
|
||||
@Override
|
||||
public void write(final JSONWriter writer, final Object value) {
|
||||
final JSONConfig config = writer.getConfig();
|
||||
// since 5.6.2可配置是否去除末尾多余0,例如如果为true,5.0返回5
|
||||
final boolean isStripTrailingZeros = (null == config) || config.isStripTrailingZeros();
|
||||
final Number number = (Number) value;
|
||||
final String numberStr = NumberUtil.toStr(number, isStripTrailingZeros);
|
||||
|
||||
final NumberWriteMode numberWriteMode = (null == config) ? NumberWriteMode.NORMAL : config.getNumberWriteMode();
|
||||
switch (numberWriteMode){
|
||||
case JS:
|
||||
if(number.longValue() > JS_MAX_NUMBER){
|
||||
writer.writeQuoteStrValue(numberStr);
|
||||
} else{
|
||||
writer.writeRaw(numberStr);
|
||||
}
|
||||
break;
|
||||
case STRING:
|
||||
writer.writeQuoteStrValue(numberStr);
|
||||
break;
|
||||
default:
|
||||
writer.writeRaw(numberStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ package org.dromara.hutool.json;
|
||||
import lombok.ToString;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.JSONSerializer;
|
||||
import org.dromara.hutool.json.serializer.SerializerManager;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -30,7 +30,7 @@ public class CustomSerializeTest {
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
SerializerManager.getInstance().register(CustomBean.class,
|
||||
TypeAdapterManager.getInstance().register(CustomBean.class,
|
||||
(JSONSerializer<CustomBean>) (bean, context) ->
|
||||
((JSONObject)context.getContextJson()).set("customName", bean.name));
|
||||
}
|
||||
@ -55,7 +55,7 @@ public class CustomSerializeTest {
|
||||
|
||||
@Test
|
||||
public void deserializeTest() {
|
||||
SerializerManager.getInstance().register(CustomBean.class, (JSONDeserializer<CustomBean>) (json, deserializeType) -> {
|
||||
TypeAdapterManager.getInstance().register(CustomBean.class, (JSONDeserializer<CustomBean>) (json, deserializeType) -> {
|
||||
final CustomBean customBean = new CustomBean();
|
||||
customBean.name = ((JSONObject) json).getStr("customName");
|
||||
return customBean;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.dromara.hutool.json;
|
||||
|
||||
import lombok.Data;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -23,12 +24,25 @@ import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* https://github.com/dromara/hutool/issues/1399<br>
|
||||
* 异常SQLException实现了Iterable导致被识别为列表,可能造成死循环,此处按照字符串处理
|
||||
* Throwable的默认序列化策略
|
||||
*/
|
||||
public class Issue1399Test {
|
||||
@Test
|
||||
void sqlExceptionTest() {
|
||||
final JSONObject set = JSONUtil.ofObj().set("error", new SQLException("test"));
|
||||
Assertions.assertEquals("{\"error\":\"java.sql.SQLException: test\"}", set.toString());
|
||||
|
||||
final String jsonStr = set.toString();
|
||||
Assertions.assertEquals("{\"error\":\"java.sql.SQLException: test\"}", jsonStr);
|
||||
|
||||
final ErrorBean bean = set.toBean(ErrorBean.class);
|
||||
Assertions.assertNotNull(bean);
|
||||
Assertions.assertNotNull(bean.getError());
|
||||
Assertions.assertEquals(SQLException.class, bean.getError().getClass());
|
||||
Assertions.assertEquals("test", bean.getError().getMessage());
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class ErrorBean {
|
||||
private SQLException error;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import lombok.Data;
|
||||
import org.dromara.hutool.json.serializer.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.JSONSerializer;
|
||||
import org.dromara.hutool.json.serializer.SerializerManager;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -29,8 +29,8 @@ import java.lang.reflect.Type;
|
||||
public class Issue2555Test {
|
||||
@Test
|
||||
public void serAndDeserTest(){
|
||||
SerializerManager.getInstance().register(MyType.class, new MySerializer());
|
||||
SerializerManager.getInstance().register(MyType.class, new MyDeserializer());
|
||||
TypeAdapterManager.getInstance().register(MyType.class, new MySerializer());
|
||||
TypeAdapterManager.getInstance().register(MyType.class, new MyDeserializer());
|
||||
|
||||
final SimpleObj simpleObj = new SimpleObj();
|
||||
final MyType child = new MyType();
|
||||
|
@ -20,7 +20,7 @@ import lombok.Data;
|
||||
import org.dromara.hutool.core.collection.ListUtil;
|
||||
import org.dromara.hutool.json.serializer.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.JSONSerializer;
|
||||
import org.dromara.hutool.json.serializer.SerializerManager;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -33,7 +33,7 @@ public class Issue3086Test {
|
||||
|
||||
@Test
|
||||
public void serializeTest() {
|
||||
SerializerManager.getInstance().register(TestBean.class, new TestBean());
|
||||
TypeAdapterManager.getInstance().register(TestBean.class, new TestBean());
|
||||
|
||||
final List<SimpleGrantedAuthority> strings = ListUtil.of(
|
||||
new SimpleGrantedAuthority("ROLE_admin"),
|
||||
|
@ -17,19 +17,30 @@
|
||||
package org.dromara.hutool.json;
|
||||
|
||||
import lombok.Data;
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.serializer.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.JSONSerializer;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class Issue3504Test {
|
||||
@Test
|
||||
public void test3504() {
|
||||
// 考虑到安全性,Class默认不支持序列化和反序列化,需要自行注册
|
||||
TypeAdapterManager.getInstance().register(Class.class,
|
||||
(JSONSerializer<Class<?>>) (bean, context) -> new JSONPrimitive(bean.getName(), ObjUtil.apply(context, JSONContext::config)));
|
||||
TypeAdapterManager.getInstance().register(Class.class,
|
||||
(JSONDeserializer<Class<?>>) (json, deserializeType) -> ClassUtil.forName((String)json.asJSONPrimitive().getValue(), true, null));
|
||||
|
||||
final JsonBean jsonBean = new JsonBean();
|
||||
jsonBean.setName("test");
|
||||
jsonBean.setClasses(new Class[]{String.class});
|
||||
final String huToolJsonStr = JSONUtil.toJsonStr(jsonBean);
|
||||
Console.log(huToolJsonStr);
|
||||
final JsonBean bean = JSONUtil.toBean(huToolJsonStr, JsonBean.class);
|
||||
|
||||
final String jsonStr = JSONUtil.toJsonStr(jsonBean);
|
||||
final JsonBean bean = JSONUtil.toBean(jsonStr, JsonBean.class);
|
||||
Assertions.assertNotNull(bean);
|
||||
Assertions.assertEquals("test", bean.getName());
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
package org.dromara.hutool.json;
|
||||
|
||||
import org.dromara.hutool.core.annotation.Alias;
|
||||
import lombok.Data;
|
||||
import org.dromara.hutool.core.annotation.Alias;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -25,8 +25,10 @@ public class Issue867Test {
|
||||
|
||||
@Test
|
||||
public void toBeanTest(){
|
||||
final String json = "{\"abc_1d\":\"123\",\"abc_d\":\"456\",\"abc_de\":\"789\"}";
|
||||
final Test02 bean = JSONUtil.toBean(JSONUtil.parseObj(json),Test02.class);
|
||||
final String jsonStr = "{\"abc_1d\":\"123\",\"abc_d\":\"456\",\"abc_de\":\"789\"}";
|
||||
final JSONObject json = JSONUtil.parseObj(jsonStr);
|
||||
//Console.log(json);
|
||||
final Test02 bean = JSONUtil.toBean(json,Test02.class);
|
||||
Assertions.assertEquals("123", bean.getAbc1d());
|
||||
Assertions.assertEquals("456", bean.getAbcD());
|
||||
Assertions.assertEquals("789", bean.getAbcDe());
|
||||
|
@ -20,7 +20,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.SerializerManager;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -31,7 +31,7 @@ public class IssuesI44E4HTest {
|
||||
|
||||
@Test
|
||||
public void deserializerTest(){
|
||||
SerializerManager.getInstance().register(TestDto.class, (JSONDeserializer<TestDto>) (json, deserializeType) -> {
|
||||
TypeAdapterManager.getInstance().register(TestDto.class, (JSONDeserializer<TestDto>) (json, deserializeType) -> {
|
||||
final TestDto testDto = new TestDto();
|
||||
testDto.setMd(new AcBizModuleMd("name1", ((JSONObject)json).getStr("md")));
|
||||
return testDto;
|
||||
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.writer;
|
||||
|
||||
import lombok.Data;
|
||||
import org.dromara.hutool.core.convert.Converter;
|
||||
import org.dromara.hutool.json.JSONConfig;
|
||||
import org.dromara.hutool.json.JSONUtil;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ValueWriterManagerTest {
|
||||
|
||||
@BeforeEach
|
||||
public void init(){
|
||||
ValueWriterManager.getInstance().register(new ValueWriter() {
|
||||
@Override
|
||||
public void write(final JSONWriter writer, final Object value) {
|
||||
writer.writeRaw(String.valueOf(((CustomSubBean)value).getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(final Object value) {
|
||||
return value instanceof CustomSubBean;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customWriteTest(){
|
||||
final CustomSubBean customBean = new CustomSubBean();
|
||||
customBean.setId(12);
|
||||
customBean.setName("aaa");
|
||||
final String s = JSONUtil.toJsonStr(customBean);
|
||||
Assertions.assertEquals("12", s);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customWriteSubTest(){
|
||||
final CustomSubBean customSubBean = new CustomSubBean();
|
||||
customSubBean.setId(12);
|
||||
customSubBean.setName("aaa");
|
||||
final CustomBean customBean = new CustomBean();
|
||||
customBean.setId(1);
|
||||
customBean.setSub(customSubBean);
|
||||
|
||||
final String s = JSONUtil.toJsonStr(customBean);
|
||||
Assertions.assertEquals("{\"id\":1,\"sub\":12}", s);
|
||||
|
||||
// 自定义转换
|
||||
final JSONConfig jsonConfig = JSONConfig.of();
|
||||
final Converter converter = jsonConfig.getConverter();
|
||||
jsonConfig.setConverter((targetType, value) -> {
|
||||
if(targetType == CustomSubBean.class){
|
||||
final CustomSubBean subBean = new CustomSubBean();
|
||||
subBean.setId((Integer) value);
|
||||
return subBean;
|
||||
}
|
||||
return converter.convert(targetType, value);
|
||||
});
|
||||
final CustomBean customBean1 = JSONUtil.parseObj(s, jsonConfig).toBean(CustomBean.class);
|
||||
Assertions.assertEquals(12, customBean1.getSub().getId());
|
||||
}
|
||||
|
||||
@Data
|
||||
static class CustomSubBean {
|
||||
private int id;
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Data
|
||||
static class CustomBean{
|
||||
private int id;
|
||||
private CustomSubBean sub;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user