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
43a0201a20
commit
ff187f6fde
@ -96,6 +96,7 @@ public class Pair<L, R> implements Serializable, Cloneable {
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Pair<?, ?> pair = (Pair<?, ?>) o;
|
||||
return Objects.equals(left, pair.left) && Objects.equals(right, pair.right);
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ public class ActualTypeMapperPool {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建类中所有的泛型变量和泛型实际类型的对应关系Map
|
||||
* 创建类中所有的泛型变量和泛型实际类型的对应关系Map<br>
|
||||
*
|
||||
* @param type 被解析的包含泛型参数的类
|
||||
* @return 泛型对应关系Map
|
||||
|
@ -22,10 +22,10 @@ import java.lang.reflect.Type;
|
||||
* Type类型参考<br>
|
||||
* 通过构建一个类型参考子类,可以获取其泛型参数中的Type类型。例如:
|
||||
*
|
||||
* <pre>
|
||||
* TypeReference<List<String>> list = new TypeReference<List<String>>() {};
|
||||
* <pre>{@code
|
||||
* TypeReference<List<String>> list = new TypeReference<List<String>>() {};
|
||||
* Type t = tr.getType();
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* 此类无法应用于通配符泛型参数(wildcard parameters),比如:{@code Class<?>} 或者 {@code List? extends CharSequence>}
|
||||
*
|
||||
|
@ -45,7 +45,10 @@ public class TypeUtil {
|
||||
* @return 原始类,如果无法获取原始类,返回{@code null}
|
||||
*/
|
||||
public static Class<?> getClass(final Type type) {
|
||||
if (null != type) {
|
||||
if (null == type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type instanceof Class) {
|
||||
return (Class<?>) type;
|
||||
} else if (type instanceof ParameterizedType) {
|
||||
@ -61,13 +64,13 @@ public class TypeUtil {
|
||||
if (upperBounds.length == 1) {
|
||||
return getClass(upperBounds[0]);
|
||||
}
|
||||
} else if(type instanceof GenericArrayType){
|
||||
return Array.newInstance(getClass(((GenericArrayType)type).getGenericComponentType()), 0).getClass();
|
||||
} else if(type instanceof TypeReference){
|
||||
return getClass(((TypeReference<?>)type).getType());
|
||||
} 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;
|
||||
|
||||
throw new IllegalArgumentException("Unsupported Type: " + type.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,7 +110,7 @@ public class TypeUtil {
|
||||
return null == field ? null : field.getType();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------- Param Type
|
||||
// region ----- Param Type
|
||||
|
||||
/**
|
||||
* 获取方法的第一个参数类型<br>
|
||||
@ -190,8 +193,9 @@ public class TypeUtil {
|
||||
public static Class<?>[] getParamClasses(final Method method) {
|
||||
return null == method ? null : method.getParameterTypes();
|
||||
}
|
||||
// endregion
|
||||
|
||||
// ----------------------------------------------------------------------------------- Return Type
|
||||
// region ----- Return Type
|
||||
|
||||
/**
|
||||
* 获取方法的返回值类型<br>
|
||||
@ -218,8 +222,9 @@ public class TypeUtil {
|
||||
public static Class<?> getReturnClass(final Method method) {
|
||||
return null == method ? null : method.getReturnType();
|
||||
}
|
||||
// endregion
|
||||
|
||||
// ----------------------------------------------------------------------------------- Type Argument
|
||||
// region ----- Type Argument
|
||||
|
||||
/**
|
||||
* 获得给定类的第一个泛型参数
|
||||
@ -267,6 +272,7 @@ public class TypeUtil {
|
||||
final ParameterizedType parameterizedType = toParameterizedType(type);
|
||||
return (null == parameterizedType) ? null : parameterizedType.getActualTypeArguments();
|
||||
}
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* 将{@link Type} 转换为{@link ParameterizedType}<br>
|
||||
@ -347,7 +353,7 @@ public class TypeUtil {
|
||||
if (ArrayUtil.isNotEmpty(genericInterfaces)) {
|
||||
for (final Type genericInterface : genericInterfaces) {
|
||||
final ParameterizedType parameterizedType = toParameterizedType(genericInterface);
|
||||
if(null != parameterizedType){
|
||||
if (null != parameterizedType) {
|
||||
result.add(parameterizedType);
|
||||
}
|
||||
}
|
||||
@ -383,20 +389,7 @@ public class TypeUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取泛型变量和泛型实际类型的对应关系Map,例如:
|
||||
*
|
||||
* <pre>
|
||||
* T org.dromara.hutool.test.User
|
||||
* E java.lang.Integer
|
||||
* </pre>
|
||||
*
|
||||
* @param clazz 被解析的包含泛型参数的类
|
||||
* @return 泛型对应关系Map
|
||||
*/
|
||||
public static Map<Type, Type> getTypeMap(final Class<?> clazz) {
|
||||
return ActualTypeMapperPool.get(clazz);
|
||||
}
|
||||
// region ----- Actual type
|
||||
|
||||
/**
|
||||
* 获得泛型字段对应的泛型实际类型,如果此变量没有对应的实际类型,返回null
|
||||
@ -417,7 +410,7 @@ public class TypeUtil {
|
||||
* 此方法可以处理:
|
||||
*
|
||||
* <pre>
|
||||
* 1. 泛型化对象,类似于Map<User, Key<Long>>
|
||||
* 1. 泛型化对象,类似于{@code Map<User, Key<Long>>}
|
||||
* 2. 泛型变量,类似于T
|
||||
* </pre>
|
||||
*
|
||||
@ -431,17 +424,30 @@ public class TypeUtil {
|
||||
}
|
||||
|
||||
if (typeVariable instanceof TypeVariable) {
|
||||
// TODO TypeReference无效
|
||||
return ActualTypeMapperPool.getActualType(type, (TypeVariable<?>) typeVariable);
|
||||
return getActualType(type, (TypeVariable<?>) typeVariable);
|
||||
}
|
||||
|
||||
// 没有需要替换的泛型变量,原样输出
|
||||
return typeVariable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得泛型变量对应的泛型实际类型,如果此变量没有对应的实际类型,返回typeVariable
|
||||
*
|
||||
* @param type 类
|
||||
* @param typeVariable 泛型变量
|
||||
* @return 实际类型,可能为Class等
|
||||
*/
|
||||
public static Type getActualType(final Type type, final TypeVariable<?> typeVariable) {
|
||||
return ObjUtil.defaultIfNull(ActualTypeMapperPool.getActualType(type, typeVariable), typeVariable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得泛型变量对应的泛型实际类型,如果此变量没有对应的实际类型,返回null
|
||||
* 此方法可以处理复杂的泛型化对象,类似于Map<User, Key<Long>>
|
||||
* 此方法可以处理复杂的泛型化对象,类似于:
|
||||
* <pre>{@code
|
||||
* Map<User, Key<Long>>
|
||||
* }</pre>
|
||||
*
|
||||
* @param type 类
|
||||
* @param parameterizedType 泛型变量,例如List<T>等
|
||||
@ -473,4 +479,20 @@ public class TypeUtil {
|
||||
public static Type[] getActualTypes(final Type type, final Type... typeVariables) {
|
||||
return ActualTypeMapperPool.getActualTypes(type, typeVariables);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取泛型变量和泛型实际类型的对应关系Map,例如:
|
||||
*
|
||||
* <pre>
|
||||
* T org.dromara.hutool.test.User
|
||||
* E java.lang.Integer
|
||||
* </pre>
|
||||
*
|
||||
* @param clazz 被解析的包含泛型参数的类
|
||||
* @return 泛型对应关系Map
|
||||
*/
|
||||
public static Map<Type, Type> getTypeMap(final Class<?> clazz) {
|
||||
return ActualTypeMapperPool.get(clazz);
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
@ -28,6 +28,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
*/
|
||||
public class DefaultRegexDateParserTest {
|
||||
|
||||
@Test
|
||||
void parseYearMonthDaySplitByDashedWithTTest() {
|
||||
assertParse("2021-03-17 06:31:33", "2021-03-17T06:31:33");
|
||||
assertParse("2021-03-17 06:31:33", "2021-03-17T06:31:33.999");
|
||||
assertParse("2021-03-17 06:31:33", "2021-03-17T06:31:33.9999");
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseYearMonthDaySplitByDashedTest() {
|
||||
assertParse("2013-02-03 00:00:00", "2013-Feb-03");
|
||||
|
@ -18,6 +18,7 @@ package org.dromara.hutool.json;
|
||||
|
||||
import org.dromara.hutool.core.bean.path.BeanPath;
|
||||
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;
|
||||
@ -231,10 +232,29 @@ public interface JSON extends Serializable {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> T toBean(final Type type) {
|
||||
if(null == type || Object.class == type){
|
||||
if(this instanceof JSONPrimitive){
|
||||
return (T) ((JSONPrimitive) this).getValue();
|
||||
}
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
final JSONDeserializer<Object> deserializer = TypeAdapterManager.getInstance().getDeserializer(this, type);
|
||||
final boolean ignoreError = ObjUtil.defaultIfNull(config(), JSONConfig::isIgnoreError, false);
|
||||
if(null == deserializer){
|
||||
if(ignoreError){
|
||||
return null;
|
||||
}
|
||||
throw new JSONException("No deserializer for type: " + type);
|
||||
}
|
||||
|
||||
try{
|
||||
return (T) deserializer.deserialize(this, type);
|
||||
} catch (final Exception e){
|
||||
if(ignoreError){
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ 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.core.reflect.ClassUtil;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
import org.dromara.hutool.json.writer.NumberWriteMode;
|
||||
|
||||
@ -51,7 +52,22 @@ public class JSONPrimitive implements Wrapper<Object>, JSON {
|
||||
* @return 是否为JSONPrimitive类型
|
||||
*/
|
||||
public static boolean isTypeForJSONPrimitive(final Object value) {
|
||||
return value instanceof Boolean || value instanceof Number || value instanceof String;
|
||||
return value instanceof Boolean
|
||||
|| value instanceof Number
|
||||
|| value instanceof Character
|
||||
|| value instanceof String;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断给定类是否可以转为JSONPrimitive类型
|
||||
*
|
||||
* @param type 值
|
||||
* @return 是否为JSONPrimitive类型
|
||||
*/
|
||||
public static boolean isTypeForJSONPrimitive(final Class<?> type) {
|
||||
return ClassUtil.isBasicType(type)
|
||||
|| Number.class.isAssignableFrom(type)
|
||||
|| String.class == type;
|
||||
}
|
||||
|
||||
private Object value;
|
||||
|
@ -27,6 +27,7 @@ import org.dromara.hutool.json.mapper.JSONValueMapper;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
import org.dromara.hutool.json.xml.JSONXMLUtil;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
@ -118,7 +119,10 @@ public class JSONUtil {
|
||||
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@link Predicate#test(Object)}为{@code true}保留
|
||||
* @return JSONObject
|
||||
*/
|
||||
public static JSONObject parseObj(final Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
public static JSONObject parseObj(Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
if(obj instanceof byte[]){
|
||||
obj = new ByteArrayInputStream((byte[]) obj);
|
||||
}
|
||||
return (JSONObject) parse(obj, config, predicate);
|
||||
}
|
||||
|
||||
|
@ -1,254 +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.convert;
|
||||
|
||||
import org.dromara.hutool.core.bean.BeanUtil;
|
||||
import org.dromara.hutool.core.bean.copier.BeanCopier;
|
||||
import org.dromara.hutool.core.convert.*;
|
||||
import org.dromara.hutool.core.convert.impl.DateConverter;
|
||||
import org.dromara.hutool.core.convert.impl.TemporalAccessorConverter;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeReference;
|
||||
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.*;
|
||||
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.TypeAdapterManager;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* JSON转换器,实现Object对象转换为{@link JSON},支持的对象:
|
||||
* <ul>
|
||||
* <li>任意支持的对象,转换为JSON</li>
|
||||
* <li>JSON转换为指定对象Bean</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class JSONConverter implements Converter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final JSONConverter INSTANCE = new JSONConverter(null);
|
||||
|
||||
/**
|
||||
* 创建JSON转换器
|
||||
*
|
||||
* @param config JSON配置
|
||||
* @return JSONConverter
|
||||
*/
|
||||
public static JSONConverter of(final JSONConfig config) {
|
||||
final JSONConverter jsonConverter = new JSONConverter(config);
|
||||
jsonConverter.registerConverter = new RegisterConverter(jsonConverter)
|
||||
.register(JSONObject.class, INSTANCE)
|
||||
.register(JSONArray.class, INSTANCE)
|
||||
.register(JSONPrimitive.class, INSTANCE);
|
||||
jsonConverter.specialConverter = new SpecialConverter(jsonConverter);
|
||||
return jsonConverter;
|
||||
}
|
||||
|
||||
private final JSONConfig config;
|
||||
private RegisterConverter registerConverter;
|
||||
private SpecialConverter specialConverter;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param config JSON配置
|
||||
*/
|
||||
private JSONConverter(final JSONConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Type targetType, final Object value) throws ConvertException {
|
||||
if (null == value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// JSON转对象
|
||||
if (value instanceof JSON) {
|
||||
if (targetType instanceof TypeReference) {
|
||||
// 还原原始类型
|
||||
targetType = ((TypeReference<?>) targetType).getType();
|
||||
}
|
||||
return toBean(targetType, (JSON) value);
|
||||
}
|
||||
|
||||
// 对象转JSON
|
||||
final Class<?> targetClass = TypeUtil.getClass(targetType);
|
||||
if (null != targetClass) {
|
||||
if (JSON.class.isAssignableFrom(targetClass)) {
|
||||
return toJSON(value);
|
||||
}
|
||||
// 自定义日期格式
|
||||
if (Date.class.isAssignableFrom(targetClass) || TemporalAccessor.class.isAssignableFrom(targetClass)) {
|
||||
final Object date = toDateWithFormat(targetClass, value);
|
||||
if (null != date) {
|
||||
return date;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ConvertUtil.convertWithCheck(targetType, value, null, config.isIgnoreError());
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现Object对象转换为JSON对象,根据RFC8259规范,支持的对象:
|
||||
* <ul>
|
||||
* <li>String: 转换为相应的对象,"和'包围的字符串返回原字符串,""返回{@code null}</li>
|
||||
* <li>Array、Iterable、Iterator:转换为JSONArray</li>
|
||||
* <li>Bean对象:转为JSONObject</li>
|
||||
* <li>Number、Boolean:返回原对象</li>
|
||||
* <li>null:返回{@code null}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 被转换的对象
|
||||
* @return 转换后的对象
|
||||
* @throws JSONException 转换异常
|
||||
*/
|
||||
public JSON toJSON(final Object obj) throws JSONException {
|
||||
if (null == obj) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSONValueMapper.of(config, null).map(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现{@link CharSequence}转换为JSON对象,根据RFC8259规范<br>
|
||||
* 转换为相应的对象,"和'包围的字符串返回原字符串,""返回{@code null}
|
||||
*
|
||||
* @param str 被转换的字符串
|
||||
* @return 转换后的对象
|
||||
* @throws JSONException 转换异常
|
||||
*/
|
||||
public JSON toJSON(final CharSequence str) throws JSONException {
|
||||
if (null == str) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String jsonStr = StrUtil.trim(str);
|
||||
if (jsonStr.isEmpty()) {
|
||||
// https://www.rfc-editor.org/rfc/rfc8259#section-7
|
||||
// 未被包装的空串理解为null
|
||||
return null;
|
||||
}
|
||||
|
||||
// RFC8259,JSON字符串值、number, boolean, or null
|
||||
final JSONParser jsonParser = JSONParser.of(new JSONTokener(jsonStr), config);
|
||||
return jsonParser.parse();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* JSON转Bean,流程为:
|
||||
* <pre>{@code
|
||||
* 自定义反序列化 --> 尝试转Kotlin --> 基于注册的标准转换器 --> Collection、Map等含有泛型的特殊转换器 --> 普通Bean转换器
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param targetType 目标类型,
|
||||
* @param json JSON
|
||||
* @return bean
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T toBean(final Type targetType, final JSON json) {
|
||||
// 自定义对象反序列化
|
||||
final JSONDeserializer<?> deserializer = TypeAdapterManager.getInstance().getDeserializer(json, targetType);
|
||||
if (null != deserializer) {
|
||||
return (T) deserializer.deserialize(json, targetType);
|
||||
}
|
||||
|
||||
// 当目标类型不确定时,返回原JSON
|
||||
final Class<T> rawType = (Class<T>) TypeUtil.getClass(targetType);
|
||||
if (null == rawType || JSON.class.isAssignableFrom(rawType)) {
|
||||
return (T) json;
|
||||
//throw new JSONException("Can not get class from type: {}", targetType);
|
||||
}
|
||||
|
||||
final Object value;
|
||||
// JSON原始类型
|
||||
if (json instanceof JSONPrimitive) {
|
||||
value = ((JSONPrimitive) json).getValue();
|
||||
} else {
|
||||
value = json;
|
||||
}
|
||||
|
||||
final JSONConfig config = ObjUtil.defaultIfNull(json.config(), JSONConfig::of);
|
||||
final boolean ignoreError = config.isIgnoreError();
|
||||
try {
|
||||
// 标准转换器
|
||||
final Converter converter = registerConverter.getConverter(targetType, value, true);
|
||||
if (null != converter) {
|
||||
return (T) converter.convert(targetType, value);
|
||||
}
|
||||
|
||||
// 特殊类型转换,包括Collection、Map、强转、Array等
|
||||
final T result = (T) specialConverter.convert(targetType, rawType, value);
|
||||
if (null != result) {
|
||||
return result;
|
||||
}
|
||||
} catch (final ConvertException e) {
|
||||
if (ignoreError) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试转Bean
|
||||
if (!(json instanceof JSONPrimitive) && BeanUtil.isWritableBean(rawType)) {
|
||||
return BeanCopier.of(value,
|
||||
ConstructorUtil.newInstanceIfPossible(rawType), targetType,
|
||||
InternalJSONUtil.toCopyOptions(config)).copy();
|
||||
}
|
||||
|
||||
// 跳过异常时返回null
|
||||
if (ignoreError) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 无法转换
|
||||
throw new JSONException("Can not convert from '{}': {} to '{}'",
|
||||
json.getClass().getName(), json, targetType.getTypeName());
|
||||
}
|
||||
|
||||
private Object toDateWithFormat(final Class<?> targetDateClass, final Object value) {
|
||||
// 日期转换,支持自定义日期格式
|
||||
final String format = config.getDateFormat();
|
||||
if (StrUtil.isNotBlank(format)) {
|
||||
if (Date.class.isAssignableFrom(targetDateClass)) {
|
||||
return new DateConverter(format).convert(targetDateClass, value);
|
||||
} else {
|
||||
return new TemporalAccessorConverter(format).convert(targetDateClass, value);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// ----------------------------------------------------------- Private method end
|
||||
}
|
@ -1,52 +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.convert;
|
||||
|
||||
import org.dromara.hutool.core.bean.copier.ValueProvider;
|
||||
import org.dromara.hutool.json.JSONGetter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* JSONGetter的ValueProvider
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @author looly
|
||||
*/
|
||||
public class JSONGetterValueProvider<K> implements ValueProvider<K> {
|
||||
|
||||
private final JSONGetter<K> jsonGetter;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param jsonGetter {@link JSONGetter}
|
||||
*/
|
||||
public JSONGetterValueProvider(final JSONGetter<K> jsonGetter) {
|
||||
this.jsonGetter = jsonGetter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object value(final K key, final Type valueType) {
|
||||
return jsonGetter.get(key, valueType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(final K key) {
|
||||
return !jsonGetter.isNull(key);
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ import java.util.Date;
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class DateSerDesc implements GsonSerDesc<Date> {
|
||||
public class DateSerDesc implements GsonTypeAdapter<Date> {
|
||||
|
||||
/**
|
||||
* 默认日期格式化描述,默认为null,表示使用时间戳
|
||||
|
@ -116,11 +116,11 @@ public class GsonEngine extends AbstractJSONEngine implements Wrapper<Gson> {
|
||||
private void registerDate(final GsonBuilder builder, final String dateFormat){
|
||||
// java date
|
||||
builder.registerTypeHierarchyAdapter(Date.class, new DateSerDesc(dateFormat));
|
||||
builder.registerTypeHierarchyAdapter(TimeZone.class, TimeZoneSerDesc.INSTANCE);
|
||||
builder.registerTypeHierarchyAdapter(TimeZone.class, TimeZoneGsonTypeAdapter.INSTANCE);
|
||||
|
||||
// java.time
|
||||
builder.registerTypeAdapter(LocalDateTime.class, new TemporalSerDesc(LocalDateTime.class, dateFormat));
|
||||
builder.registerTypeAdapter(LocalDate.class, new TemporalSerDesc(LocalDate.class, dateFormat));
|
||||
builder.registerTypeAdapter(LocalTime.class, new TemporalSerDesc(LocalTime.class, dateFormat));
|
||||
builder.registerTypeAdapter(LocalDateTime.class, new TemporalGsonTypeAdapter(LocalDateTime.class, dateFormat));
|
||||
builder.registerTypeAdapter(LocalDate.class, new TemporalGsonTypeAdapter(LocalDate.class, dateFormat));
|
||||
builder.registerTypeAdapter(LocalTime.class, new TemporalGsonTypeAdapter(LocalTime.class, dateFormat));
|
||||
}
|
||||
}
|
||||
|
@ -26,5 +26,5 @@ import com.google.gson.JsonSerializer;
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public interface GsonSerDesc<T> extends JsonSerializer<T>, JsonDeserializer<T> {
|
||||
public interface GsonTypeAdapter<T> extends JsonSerializer<T>, JsonDeserializer<T> {
|
||||
}
|
@ -30,7 +30,7 @@ import java.time.temporal.TemporalAccessor;
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class TemporalSerDesc implements GsonSerDesc<TemporalAccessor> {
|
||||
public class TemporalGsonTypeAdapter implements GsonTypeAdapter<TemporalAccessor> {
|
||||
|
||||
private final Class<? extends TemporalAccessor> type;
|
||||
private final String dateFormat;
|
||||
@ -41,7 +41,7 @@ public class TemporalSerDesc implements GsonSerDesc<TemporalAccessor> {
|
||||
* @param type 时间类型
|
||||
* @param dateFormat 日期格式
|
||||
*/
|
||||
public TemporalSerDesc(final Class<? extends TemporalAccessor> type, final String dateFormat) {
|
||||
public TemporalGsonTypeAdapter(final Class<? extends TemporalAccessor> type, final String dateFormat) {
|
||||
this.type = type;
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
@ -27,12 +27,12 @@ import java.util.TimeZone;
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class TimeZoneSerDesc implements GsonSerDesc<TimeZone>{
|
||||
public class TimeZoneGsonTypeAdapter implements GsonTypeAdapter<TimeZone> {
|
||||
|
||||
/**
|
||||
* 默认时区格式化描述
|
||||
*/
|
||||
public static final TimeZoneSerDesc INSTANCE = new TimeZoneSerDesc();
|
||||
public static final TimeZoneGsonTypeAdapter INSTANCE = new TimeZoneGsonTypeAdapter();
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(final TimeZone src, final Type typeOfSrc, final JsonSerializationContext context) {
|
@ -16,8 +16,6 @@
|
||||
|
||||
package org.dromara.hutool.json.mapper;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.collection.iter.ArrayIter;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||
import org.dromara.hutool.json.JSONArray;
|
||||
@ -26,7 +24,6 @@ import org.dromara.hutool.json.JSONException;
|
||||
import org.dromara.hutool.json.reader.JSONParser;
|
||||
import org.dromara.hutool.json.reader.JSONTokener;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
@ -90,51 +87,10 @@ class JSONArrayMapper {
|
||||
jsonArray.set(b);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final Iterator<?> iter;
|
||||
if (ArrayUtil.isArray(source)) {// 数组
|
||||
iter = new ArrayIter<>(source);
|
||||
} else if (source instanceof Iterator<?>) {// Iterator
|
||||
iter = ((Iterator<?>) source);
|
||||
} else if (source instanceof Iterable<?>) {// Iterable
|
||||
iter = ((Iterable<?>) source).iterator();
|
||||
} else {
|
||||
if (!jsonArray.config().isIgnoreError()) {
|
||||
}
|
||||
|
||||
throw new JSONException("Unsupported [{}] to JSONArray", source.getClass());
|
||||
}
|
||||
// 如果用户选择跳过异常,则跳过此值转换
|
||||
return;
|
||||
}
|
||||
|
||||
mapFromIterator(iter, jsonArray);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Iterator中读取数据,并添加到JSONArray中
|
||||
*
|
||||
* @param iter {@link Iterator}
|
||||
* @param jsonArray {@link JSONArray}
|
||||
*/
|
||||
private void mapFromIterator(final Iterator<?> iter, final JSONArray jsonArray) {
|
||||
Object next;
|
||||
while (iter.hasNext()) {
|
||||
next = iter.next();
|
||||
// 检查循环引用
|
||||
if (next != source) {
|
||||
if (null != this.predicate) {
|
||||
final MutableEntry<Object, Object> entry = MutableEntry.of(jsonArray.size(), next);
|
||||
if (predicate.test(entry)) {
|
||||
// 使用修改后的键值对
|
||||
next = entry.getValue();
|
||||
jsonArray.set(next);
|
||||
}
|
||||
} else {
|
||||
jsonArray.set(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从JSONTokener中读取数据,并添加到JSONArray中
|
||||
|
@ -16,14 +16,8 @@
|
||||
|
||||
package org.dromara.hutool.json.mapper;
|
||||
|
||||
import org.dromara.hutool.core.bean.BeanUtil;
|
||||
import org.dromara.hutool.core.bean.RecordUtil;
|
||||
import org.dromara.hutool.core.bean.copier.CopyOptions;
|
||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.json.InternalJSONUtil;
|
||||
import org.dromara.hutool.json.JSONConfig;
|
||||
import org.dromara.hutool.json.JSONException;
|
||||
@ -31,9 +25,7 @@ import org.dromara.hutool.json.JSONObject;
|
||||
import org.dromara.hutool.json.reader.JSONParser;
|
||||
import org.dromara.hutool.json.reader.JSONTokener;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@ -81,32 +73,17 @@ class JSONObjectMapper {
|
||||
*
|
||||
* @param jsonObject 目标{@link JSONObject}
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void mapTo(final JSONObject jsonObject) {
|
||||
final Object source = this.source;
|
||||
if (null == source) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (source instanceof Map) {
|
||||
// Map
|
||||
for (final Map.Entry<?, ?> e : ((Map<?, ?>) source).entrySet()) {
|
||||
jsonObject.set(ConvertUtil.toStr(e.getKey()), e.getValue());
|
||||
}
|
||||
} else if (source instanceof Map.Entry) {
|
||||
final Map.Entry entry = (Map.Entry) source;
|
||||
jsonObject.set(ConvertUtil.toStr(entry.getKey()), entry.getValue());
|
||||
} else if (source instanceof byte[]) {
|
||||
if (source instanceof byte[]) {
|
||||
mapFromTokener(new JSONTokener(IoUtil.toStream((byte[]) source)), jsonObject.config(), jsonObject);
|
||||
} else if (source instanceof ResourceBundle) {
|
||||
// ResourceBundle
|
||||
mapFromResourceBundle((ResourceBundle) source, jsonObject);
|
||||
} else if (RecordUtil.isRecord(source.getClass())) {
|
||||
// since 6.0.0
|
||||
mapFromRecord(source, jsonObject);
|
||||
} else if (BeanUtil.isReadableBean(source.getClass())) {
|
||||
// 普通Bean
|
||||
mapFromBean(source, jsonObject);
|
||||
} else {
|
||||
if (!jsonObject.config().isIgnoreError()) {
|
||||
// 不支持对象类型转换为JSONObject
|
||||
@ -142,36 +119,4 @@ class JSONObjectMapper {
|
||||
private void mapFromTokener(final JSONTokener x, final JSONConfig config, final JSONObject jsonObject) {
|
||||
JSONParser.of(x, config).setPredicate(this.predicate).parseTo(jsonObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Record转换
|
||||
*
|
||||
* @param record Record对象
|
||||
* @param jsonObject {@link JSONObject}
|
||||
*/
|
||||
private void mapFromRecord(final Object record, final JSONObject jsonObject) {
|
||||
final Map.Entry<String, Type>[] components = RecordUtil.getRecordComponents(record.getClass());
|
||||
|
||||
String key;
|
||||
for (final Map.Entry<String, Type> entry : components) {
|
||||
key = entry.getKey();
|
||||
jsonObject.set(key, MethodUtil.invoke(record, key));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Bean转换
|
||||
*
|
||||
* @param bean Bean对象
|
||||
* @param jsonObject {@link JSONObject}
|
||||
*/
|
||||
private void mapFromBean(final Object bean, final JSONObject jsonObject) {
|
||||
final CopyOptions copyOptions = InternalJSONUtil.toCopyOptions(jsonObject.config());
|
||||
if (null != this.predicate) {
|
||||
copyOptions.setFieldEditor((entry -> this.predicate.test(
|
||||
MutableEntry.of(StrUtil.toStringOrNull(entry.getKey()), entry.getValue())) ?
|
||||
entry : null));
|
||||
}
|
||||
BeanUtil.beanToMap(bean, jsonObject, copyOptions);
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,11 @@
|
||||
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.lang.tuple.Pair;
|
||||
import org.dromara.hutool.core.lang.tuple.Triple;
|
||||
import org.dromara.hutool.core.lang.tuple.Tuple;
|
||||
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;
|
||||
@ -28,6 +29,8 @@ import org.dromara.hutool.json.JSONException;
|
||||
import org.dromara.hutool.json.serializer.impl.*;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@ -57,11 +60,7 @@ public class TypeAdapterManager {
|
||||
/**
|
||||
* 静态初始化器,由JVM来保证线程安全
|
||||
*/
|
||||
private static final TypeAdapterManager INSTANCE = new TypeAdapterManager();
|
||||
|
||||
static {
|
||||
registerDefault(INSTANCE);
|
||||
}
|
||||
private static final TypeAdapterManager INSTANCE = registerDefault(new TypeAdapterManager());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,9 +78,7 @@ public class TypeAdapterManager {
|
||||
* @return SerializerManager
|
||||
*/
|
||||
public static TypeAdapterManager of() {
|
||||
final TypeAdapterManager typeAdapterManager = new TypeAdapterManager();
|
||||
registerDefault(typeAdapterManager);
|
||||
return typeAdapterManager;
|
||||
return registerDefault(new TypeAdapterManager());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,20 +165,31 @@ public class TypeAdapterManager {
|
||||
*/
|
||||
@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);
|
||||
final Class<?> rawType = TypeUtil.getClass(type);
|
||||
if (null == rawType) {
|
||||
return null;
|
||||
}
|
||||
if (JSONSerializer.class.isAssignableFrom(rawType)) {
|
||||
return (JSONSerializer<Object>) ConstructorUtil.newInstanceIfPossible(rawType);
|
||||
}
|
||||
|
||||
if (null == result && CollUtil.isNotEmpty(this.serializerSet)) {
|
||||
if (MapUtil.isNotEmpty(this.serializerMap)) {
|
||||
final JSONSerializer<?> result = this.serializerMap.get(rawType);
|
||||
if(null != result){
|
||||
return (JSONSerializer<Object>) result;
|
||||
}
|
||||
}
|
||||
|
||||
// Matcher
|
||||
if (CollUtil.isNotEmpty(this.serializerSet)) {
|
||||
for (final MatcherJSONSerializer<?> serializer : this.serializerSet) {
|
||||
if (serializer.match(bean, null)) {
|
||||
result = (MatcherJSONSerializer<Object>) serializer;
|
||||
break;
|
||||
return (MatcherJSONSerializer<Object>) serializer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
throw new JSONException("No serializer for type: " + type);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -201,8 +209,8 @@ public class TypeAdapterManager {
|
||||
return (JSONDeserializer<Object>) ConstructorUtil.newInstanceIfPossible(rawType);
|
||||
}
|
||||
|
||||
if (CollUtil.isNotEmpty(this.deserializerMap)) {
|
||||
final JSONDeserializer<?> jsonDeserializer = this.deserializerMap.get(type);
|
||||
if (MapUtil.isNotEmpty(this.deserializerMap)) {
|
||||
final JSONDeserializer<?> jsonDeserializer = this.deserializerMap.get(rawType);
|
||||
if (null != jsonDeserializer) {
|
||||
return (JSONDeserializer<Object>) jsonDeserializer;
|
||||
}
|
||||
@ -226,7 +234,7 @@ public class TypeAdapterManager {
|
||||
if (null == this.serializerSet) {
|
||||
synchronized (this) {
|
||||
if (null == this.serializerSet) {
|
||||
this.serializerSet = new ConcurrentHashSet<>();
|
||||
this.serializerSet = new LinkedHashSet<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -237,7 +245,7 @@ public class TypeAdapterManager {
|
||||
if (null == this.serializerMap) {
|
||||
synchronized (this) {
|
||||
if (null == this.serializerMap) {
|
||||
this.serializerMap = new SafeConcurrentHashMap<>();
|
||||
this.serializerMap = new HashMap<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -248,7 +256,7 @@ public class TypeAdapterManager {
|
||||
if (null == this.deserializerSet) {
|
||||
synchronized (this) {
|
||||
if (null == this.deserializerSet) {
|
||||
this.deserializerSet = new ConcurrentHashSet<>();
|
||||
this.deserializerSet = new LinkedHashSet<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -259,7 +267,7 @@ public class TypeAdapterManager {
|
||||
if (null == this.deserializerMap) {
|
||||
synchronized (this) {
|
||||
if (null == this.deserializerMap) {
|
||||
this.deserializerMap = new SafeConcurrentHashMap<>();
|
||||
this.deserializerMap = new HashMap<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -271,24 +279,35 @@ public class TypeAdapterManager {
|
||||
* 注册默认的序列化器和反序列化器
|
||||
*
|
||||
* @param manager {@code SerializerManager}
|
||||
* @return TypeAdapterManager
|
||||
*/
|
||||
private static void registerDefault(final TypeAdapterManager manager) {
|
||||
// issue#I5WDP0 对于Kotlin对象,由于参数可能非空限制,导致无法创建一个默认的对象再赋值
|
||||
private static TypeAdapterManager registerDefault(final TypeAdapterManager manager) {
|
||||
|
||||
// 自定义序列化器
|
||||
|
||||
// 自定义反序列化器
|
||||
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(Triple.class, TripleDeserializer.INSTANCE);
|
||||
manager.register(Pair.class, PairDeserializer.INSTANCE);
|
||||
manager.register(Tuple.class, TupleDeserializer.INSTANCE);
|
||||
|
||||
|
||||
// 自定义类型适配器
|
||||
manager.register(JSONPrimitiveTypeAdapter.INSTANCE);
|
||||
manager.register(CharSequenceTypeAdapter.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(EntryTypeAdapter.INSTANCE);
|
||||
manager.register(MapTypeAdapter.INSTANCE);
|
||||
manager.register(IterTypeAdapter.INSTANCE);
|
||||
manager.register(ArrayTypeAdapter.INSTANCE);
|
||||
// 最低优先级
|
||||
manager.register(BeanTypeAdapter.INSTANCE);
|
||||
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,15 @@
|
||||
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.collection.iter.ArrayIter;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONArray;
|
||||
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.Array;
|
||||
import java.lang.reflect.Type;
|
||||
@ -32,12 +36,17 @@ import java.util.Map;
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class ArrayDeserializer implements MatcherJSONDeserializer<Object> {
|
||||
public class ArrayTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJSONDeserializer<Object> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final ArrayDeserializer INSTANCE = new ArrayDeserializer();
|
||||
public static final ArrayTypeAdapter INSTANCE = new ArrayTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return ArrayUtil.isArray(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
@ -47,6 +56,11 @@ public class ArrayDeserializer implements MatcherJSONDeserializer<Object> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON serialize(final Object bean, final JSONContext context) {
|
||||
return IterTypeAdapter.INSTANCE.serialize(new ArrayIter<>(bean), context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
final int size = json.size();
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.text.StrUtil;
|
||||
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.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONSerializer;
|
||||
import org.dromara.hutool.json.xml.JSONXMLParser;
|
||||
import org.dromara.hutool.json.xml.ParseConfig;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* CharSequence类型适配器,用于处理未匹配的JSON类型。
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class CharSequenceTypeAdapter implements MatcherJSONSerializer<CharSequence>, MatcherJSONDeserializer<CharSequence> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final CharSequenceTypeAdapter INSTANCE = new CharSequenceTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return bean instanceof CharSequence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
return CharSequence.class.isAssignableFrom(TypeUtil.getClass(deserializeType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON serialize(final CharSequence bean, final JSONContext context) {
|
||||
final String jsonStr = StrUtil.trim(bean);
|
||||
if (StrUtil.startWith(jsonStr, '<')) {
|
||||
// 可能为XML
|
||||
JSONObject jsonObject = (JSONObject) context.getContextJson();
|
||||
if(null == jsonObject){
|
||||
jsonObject = JSONUtil.ofObj(context.config());
|
||||
}
|
||||
JSONXMLParser.of(ParseConfig.of(), null).parseJSONObject(jsonStr, jsonObject);
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
return mapFromTokener(new JSONTokener(jsonStr), context.config());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence deserialize(final JSON json, final Type deserializeType) {
|
||||
if(json instanceof JSONPrimitive){
|
||||
return ((JSONPrimitive) json).getValue().toString();
|
||||
}
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从{@link JSONTokener} 中读取JSON字符串,并转换为JSON
|
||||
*
|
||||
* @param tokener {@link JSONTokener}
|
||||
* @return JSON
|
||||
*/
|
||||
private JSON mapFromTokener(final JSONTokener tokener, final JSONConfig config) {
|
||||
return JSONParser.of(tokener, config).setPredicate(null).parse();
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ 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.date.format.GlobalCustomFormat;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
@ -55,12 +56,20 @@ public class DateTypeAdapter implements MatcherJSONSerializer<Date>, MatcherJSON
|
||||
|
||||
@Override
|
||||
public JSON serialize(final Date bean, final JSONContext context) {
|
||||
final JSONConfig config = ObjUtil.apply(context, JSONContext::config);
|
||||
final JSONConfig config = context.config();
|
||||
final String format = ObjUtil.apply(config, JSONConfig::getDateFormat);
|
||||
return new JSONPrimitive(
|
||||
null == format
|
||||
? bean.getTime()
|
||||
: DateUtil.format(bean, format), config);
|
||||
|
||||
final Object value;
|
||||
// 默认为时间戳
|
||||
if(null == format || GlobalCustomFormat.FORMAT_MILLISECONDS.equals(format)){
|
||||
value = bean.getTime();
|
||||
} else if(GlobalCustomFormat.FORMAT_SECONDS.equals(format)){
|
||||
value = Math.floorDiv(bean.getTime(), 1000L);
|
||||
} else {
|
||||
value = DateUtil.format(bean, format);
|
||||
}
|
||||
|
||||
return new JSONPrimitive(value, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.json.*;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
@ -40,58 +39,21 @@ public class DefaultDeserializer implements JSONDeserializer<Object> {
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
// 当目标类型不确定时,返回原JSON
|
||||
final Class<?> rawType = TypeUtil.getClass(deserializeType);
|
||||
if (null == rawType || rawType == json.getClass()) {
|
||||
if (null == rawType || Object.class == rawType || rawType == json.getClass()) {
|
||||
return json;
|
||||
}
|
||||
|
||||
if (json instanceof JSONObject) {
|
||||
return fromJSONObject((JSONObject) json, deserializeType, rawType);
|
||||
} else if (json instanceof JSONArray) {
|
||||
return fromJSONArray((JSONArray) json, deserializeType, rawType);
|
||||
} else if (json instanceof JSONPrimitive) {
|
||||
return fromJSONPrimitive((JSONPrimitive) json, deserializeType, rawType);
|
||||
// JSON类型之间互转
|
||||
if(json instanceof JSONPrimitive && JSON.class.isAssignableFrom(rawType)){
|
||||
final Object value = json.asJSONPrimitive().getValue();
|
||||
if(value instanceof CharSequence){
|
||||
// JSON字符串转JSON
|
||||
return JSONUtil.parse(value, json.config());
|
||||
}
|
||||
throw new JSONException("Unsupported JSON type: {}", json.getClass());
|
||||
} else if(json instanceof JSONObject && JSONArray.class == rawType){
|
||||
return JSONUtil.parseArray(json, json.config());
|
||||
}
|
||||
|
||||
/**
|
||||
* 从JSONObject反序列化
|
||||
*
|
||||
* @param json JSONObject
|
||||
* @param deserializeType 目标类型
|
||||
* @param rawType 目标类型
|
||||
* @return 反序列化后的对象
|
||||
*/
|
||||
private Object fromJSONObject(final JSONObject json, final Type deserializeType, final Class<?> rawType) {
|
||||
throw new JSONException("Unsupported JSONObject to {}", rawType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从JSONArray反序列化
|
||||
*
|
||||
* @param json JSONArray
|
||||
* @param deserializeType 目标类型
|
||||
* @param rawType 目标类型
|
||||
* @return 反序列化后的对象
|
||||
*/
|
||||
private Object fromJSONArray(final JSONArray json, final Type deserializeType, final Class<?> rawType) {
|
||||
throw new JSONException("Unsupported JSONArray to {}", rawType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从JSONPrimitive反序列化
|
||||
*
|
||||
* @param json JSONPrimitive
|
||||
* @param deserializeType 目标类型
|
||||
* @param rawType 目标类型
|
||||
* @return 反序列化后的对象
|
||||
*/
|
||||
private Object fromJSONPrimitive(final JSONPrimitive json, final Type deserializeType, final Class<?> rawType) {
|
||||
final Object value = json.getValue();
|
||||
if (null != value && rawType.isAssignableFrom(value.getClass())) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return CompositeConverter.getInstance().convert(deserializeType, value);
|
||||
throw new JSONException("Unsupported type {} to {}", json.getClass(), deserializeType.getTypeName());
|
||||
}
|
||||
}
|
||||
|
@ -17,27 +17,36 @@
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
||||
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.JSONObject;
|
||||
import org.dromara.hutool.json.JSONUtil;
|
||||
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.Map;
|
||||
|
||||
/**
|
||||
* Map.Entry反序列化器,用于将JSON对象转换为Map.Entry对象。
|
||||
* Map.Entry序列化和反序列化器,用于将JSON对象和Map.Entry对象互转。
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class EntryDeserializer implements MatcherJSONDeserializer<Map.Entry<?, ?>> {
|
||||
public class EntryTypeAdapter implements MatcherJSONSerializer<Map.Entry<?, ?>>, MatcherJSONDeserializer<Map.Entry<?, ?>> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final EntryDeserializer INSTANCE = new EntryDeserializer();
|
||||
public static final EntryTypeAdapter INSTANCE = new EntryTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return bean instanceof Map.Entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
@ -48,6 +57,19 @@ public class EntryDeserializer implements MatcherJSONDeserializer<Map.Entry<?, ?
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON serialize(final Map.Entry<?, ?> bean, final JSONContext context) {
|
||||
final JSONObject result;
|
||||
final JSON contextJson = context.getContextJson();
|
||||
if(contextJson instanceof JSONObject){
|
||||
result = contextJson.asJSONObject();
|
||||
}else{
|
||||
result = JSONUtil.ofObj(context.config());
|
||||
}
|
||||
result.set(ConvertUtil.toStr(bean.getKey()), bean.getValue());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map.Entry<?, ?> deserialize(final JSON json, final Type deserializeType) {
|
||||
final Type keyType = TypeUtil.getTypeArgument(deserializeType, 0);
|
@ -18,39 +18,66 @@ package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.collection.CollUtil;
|
||||
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.JSONArray;
|
||||
import org.dromara.hutool.json.JSONObject;
|
||||
import org.dromara.hutool.json.JSONUtil;
|
||||
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.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 集合类型反序列化器
|
||||
* Iterator序列化器,将{@link Iterable}或{@link Iterator}转换为JSONArray
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
* @author Looly
|
||||
*/
|
||||
public class CollectionDeserializer implements MatcherJSONDeserializer<Collection<?>> {
|
||||
public class IterTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJSONDeserializer<Object> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final CollectionDeserializer INSTANCE = new CollectionDeserializer();
|
||||
public static final IterTypeAdapter INSTANCE = new IterTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return bean instanceof Iterable || bean instanceof Iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
if (json instanceof JSONArray || json instanceof JSONObject) {
|
||||
final Class<?> rawType = TypeUtil.getClass(deserializeType);
|
||||
// 反序列化只支持到集合
|
||||
return Collection.class.isAssignableFrom(rawType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> deserialize(final JSON json, final Type deserializeType) {
|
||||
public JSON serialize(final Object bean, final JSONContext context) {
|
||||
final Iterator<?> iter;
|
||||
if (bean instanceof Iterator<?>) {// Iterator
|
||||
iter = ((Iterator<?>) bean);
|
||||
} else {// Iterable
|
||||
iter = ((Iterable<?>) bean).iterator();
|
||||
}
|
||||
|
||||
JSONArray json = (JSONArray) context.getContextJson();
|
||||
if(null == json){
|
||||
json = JSONUtil.ofArray(ObjUtil.apply(context, JSONContext::config));
|
||||
}
|
||||
mapFromIterator(bean, iter, json);
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
final Class<?> rawType = TypeUtil.getClass(deserializeType);
|
||||
final Type elementType = TypeUtil.getTypeArgument(deserializeType);
|
||||
final Collection<?> result = CollUtil.create(rawType, TypeUtil.getClass(elementType));
|
||||
@ -65,6 +92,23 @@ public class CollectionDeserializer implements MatcherJSONDeserializer<Collectio
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Iterator中读取数据,并添加到JSONArray中
|
||||
*
|
||||
* @param iter {@link Iterator}
|
||||
* @param jsonArray {@link JSONArray}
|
||||
*/
|
||||
private void mapFromIterator(final Object source, final Iterator<?> iter, final JSONArray jsonArray) {
|
||||
Object next;
|
||||
while (iter.hasNext()) {
|
||||
next = iter.next();
|
||||
// 检查循环引用
|
||||
if (next != source) {
|
||||
jsonArray.set(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将JSONObject转换为集合
|
||||
*
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.ConvertUtil;
|
||||
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;
|
||||
|
||||
/**
|
||||
* {@link JSONPrimitive}相关类型适配器,用于处理数字类型的序列化和反序列化
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class JSONPrimitiveTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJSONDeserializer<Object> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final JSONPrimitiveTypeAdapter INSTANCE = new JSONPrimitiveTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return JSONPrimitive.isTypeForJSONPrimitive(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
return json instanceof JSONPrimitive && JSONPrimitive.isTypeForJSONPrimitive(TypeUtil.getClass(deserializeType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON serialize(Object bean, final JSONContext context) {
|
||||
if(bean instanceof Character){
|
||||
// 字符按照字符串存储
|
||||
bean = bean.toString();
|
||||
}
|
||||
|
||||
final JSONPrimitive json = (JSONPrimitive) context.getContextJson();
|
||||
if (null != json) {
|
||||
json.setValue(bean);
|
||||
return json;
|
||||
}
|
||||
|
||||
return new JSONPrimitive(bean, context.config());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
final Object value = json.asJSONPrimitive().getValue();
|
||||
|
||||
|
||||
if (null != value && TypeUtil.getClass(deserializeType).isAssignableFrom(value.getClass())) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return ConvertUtil.convertWithCheck(deserializeType, value, null,
|
||||
ObjUtil.apply(json.config(), JSONConfig::isIgnoreError));
|
||||
}
|
||||
}
|
@ -20,7 +20,8 @@ import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.reflect.kotlin.KClassUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONGetter;
|
||||
import org.dromara.hutool.json.convert.JSONGetterValueProvider;
|
||||
import org.dromara.hutool.json.JSONObject;
|
||||
import org.dromara.hutool.json.convert.JSONObjectValueProvider;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
@ -46,10 +47,9 @@ public class KBeanDeserializer implements MatcherJSONDeserializer<Object> {
|
||||
&& KClassUtil.isKotlinClass(rawType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
final Class<?> rawType = TypeUtil.getClass(deserializeType);
|
||||
return KClassUtil.newInstance(rawType, new JSONGetterValueProvider<>((JSONGetter<String>) json));
|
||||
return KClassUtil.newInstance(rawType, new JSONObjectValueProvider((JSONObject) json));
|
||||
}
|
||||
}
|
||||
|
@ -17,28 +17,38 @@
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
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.JSONObject;
|
||||
import org.dromara.hutool.json.JSONUtil;
|
||||
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.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Map反序列化器,用于将JSON对象转换为Map对象。
|
||||
* Map类型适配器器,用于将JSON对象和Map对象互转。
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class MapDeserializer implements MatcherJSONDeserializer<Map<?, ?>> {
|
||||
public class MapTypeAdapter implements MatcherJSONSerializer<Map<?, ?>>, MatcherJSONDeserializer<Map<?, ?>> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final MapDeserializer INSTANCE = new MapDeserializer();
|
||||
public static final MapTypeAdapter INSTANCE = new MapTypeAdapter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
return bean instanceof Map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
@ -49,6 +59,19 @@ public class MapDeserializer implements MatcherJSONDeserializer<Map<?, ?>> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSON serialize(final Map<?, ?> bean, final JSONContext context) {
|
||||
final JSON contextJson = context.getContextJson();
|
||||
final JSONObject result = contextJson instanceof JSONObject ?
|
||||
(JSONObject) contextJson : JSONUtil.ofObj(context.config());
|
||||
|
||||
// 注入键值对
|
||||
for (final Map.Entry<?, ?> e : bean.entrySet()) {
|
||||
result.set(ConvertUtil.toStr(e.getKey()), e.getValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public Map<?, ?> deserialize(final JSON json, final Type deserializeType) {
|
||||
@ -60,7 +83,7 @@ public class MapDeserializer implements MatcherJSONDeserializer<Map<?, ?>> {
|
||||
map.put(
|
||||
// key类型为String转目标类型,使用标准转换器
|
||||
CompositeConverter.getInstance().convert(keyType, entry.getKey()),
|
||||
entry.getValue().toBean(valueType)
|
||||
ObjUtil.apply(entry.getValue(), (value)-> value.toBean(valueType))
|
||||
);
|
||||
}
|
||||
return map;
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.lang.tuple.Pair;
|
||||
import org.dromara.hutool.core.reflect.TypeReference;
|
||||
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.JSONDeserializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 二元组反序列化器
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class PairDeserializer implements JSONDeserializer<Pair<?, ?>> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final PairDeserializer INSTANCE = new PairDeserializer();
|
||||
|
||||
@Override
|
||||
public Pair<?, ?> deserialize(final JSON json, Type deserializeType) {
|
||||
if (deserializeType instanceof TypeReference) {
|
||||
deserializeType = ((TypeReference<?>) deserializeType).getType();
|
||||
}
|
||||
final Type leftType = TypeUtil.getTypeArgument(deserializeType, 0);
|
||||
final Type rightType = TypeUtil.getTypeArgument(deserializeType, 2);
|
||||
|
||||
final JSONObject jsonObject = json.asJSONObject();
|
||||
final JSON left = jsonObject.get("left");
|
||||
final JSON right = jsonObject.get("right");
|
||||
|
||||
return Pair.of(
|
||||
left.toBean(leftType),
|
||||
right.toBean(rightType)
|
||||
);
|
||||
}
|
||||
}
|
@ -17,20 +17,20 @@
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.impl.TemporalAccessorConverter;
|
||||
import org.dromara.hutool.core.date.TimeUtil;
|
||||
import org.dromara.hutool.core.date.format.GlobalCustomFormat;
|
||||
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.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.*;
|
||||
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.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Month;
|
||||
import java.time.*;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
|
||||
/**
|
||||
@ -70,13 +70,70 @@ public class TemporalTypeAdapter implements MatcherJSONSerializer<TemporalAccess
|
||||
|
||||
@Override
|
||||
public JSON serialize(final TemporalAccessor bean, final JSONContext context) {
|
||||
final JSONObject json;
|
||||
final JSONConfig config = context.config();
|
||||
|
||||
final JSON contextJson = context.getContextJson();
|
||||
if(contextJson instanceof JSONObject){
|
||||
json = (JSONObject) contextJson;
|
||||
}else {
|
||||
json = new JSONObject((int) (7F / 0.75F + 1F), context.config());
|
||||
toJSONObject(bean, contextJson.asJSONObject());
|
||||
return contextJson;
|
||||
}
|
||||
|
||||
if (bean instanceof Month) {
|
||||
return new JSONPrimitive(((Month) bean).getValue(), config);
|
||||
} else if (bean instanceof DayOfWeek) {
|
||||
return new JSONPrimitive(((DayOfWeek) bean).getValue(), config);
|
||||
} else if (bean instanceof MonthDay) {
|
||||
return new JSONPrimitive(((MonthDay) bean).toString(), config);
|
||||
}
|
||||
|
||||
final String format = ObjUtil.apply(config, JSONConfig::getDateFormat);
|
||||
|
||||
final Object value;
|
||||
// 默认为时间戳
|
||||
if (null == format || GlobalCustomFormat.FORMAT_MILLISECONDS.equals(format)) {
|
||||
value = TimeUtil.toEpochMilli(bean);
|
||||
} else if (GlobalCustomFormat.FORMAT_SECONDS.equals(format)) {
|
||||
value = Math.floorDiv(TimeUtil.toEpochMilli(bean), 1000L);
|
||||
} else {
|
||||
value = TimeUtil.format(bean, format);
|
||||
}
|
||||
|
||||
return new JSONPrimitive(value, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemporalAccessor deserialize(final JSON json, final Type deserializeType) {
|
||||
// JSONPrimitive
|
||||
if (json instanceof JSONPrimitive) {
|
||||
final Object value = ((JSONPrimitive) json).getValue();
|
||||
final TemporalAccessorConverter converter = new TemporalAccessorConverter(
|
||||
Opt.ofNullable(json.config()).map(JSONConfig::getDateFormat).getOrNull());
|
||||
return (TemporalAccessor) converter.convert(deserializeType, value);
|
||||
}
|
||||
|
||||
final Class<?> temporalAccessorClass = TypeUtil.getClass(deserializeType);
|
||||
if (json instanceof JSONObject) {
|
||||
return fromJSONObject(temporalAccessorClass, json.asJSONObject());
|
||||
}
|
||||
|
||||
if (Month.class.equals(temporalAccessorClass)) {
|
||||
return Month.of((Integer) json.asJSONPrimitive().getValue());
|
||||
} else if (DayOfWeek.class.equals(temporalAccessorClass)) {
|
||||
return DayOfWeek.of((Integer) json.asJSONPrimitive().getValue());
|
||||
} else if (MonthDay.class.equals(temporalAccessorClass)) {
|
||||
return MonthDay.parse((CharSequence) json.asJSONPrimitive().getValue());
|
||||
}
|
||||
|
||||
throw new JSONException("Unsupported type from JSON {} to {}", json, deserializeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将{@link TemporalAccessor}转换为JSONObject
|
||||
*
|
||||
* @param bean {@link TemporalAccessor}
|
||||
* @param json JSONObject
|
||||
*/
|
||||
private static void toJSONObject(final TemporalAccessor bean, final JSONObject json) {
|
||||
if (bean instanceof LocalDate) {
|
||||
final LocalDate localDate = (LocalDate) bean;
|
||||
json.set(YEAR_KEY, localDate.getYear());
|
||||
@ -97,27 +154,18 @@ public class TemporalTypeAdapter implements MatcherJSONSerializer<TemporalAccess
|
||||
json.set(MINUTE_KEY, localTime.getMinute());
|
||||
json.set(SECOND_KEY, localTime.getSecond());
|
||||
json.set(NANO_KEY, localTime.getNano());
|
||||
} else {
|
||||
throw new JSONException("Unsupported TemporalAccessor type to JSON: {}", bean.getClass().getName());
|
||||
}
|
||||
return json;
|
||||
throw new JSONException("Unsupported type {}.", bean.getClass().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemporalAccessor deserialize(final JSON json, final Type deserializeType) {
|
||||
// JSONPrimitive
|
||||
if(json instanceof JSONPrimitive){
|
||||
final Object value = ((JSONPrimitive) json).getValue();
|
||||
final TemporalAccessorConverter converter = new TemporalAccessorConverter(
|
||||
Opt.ofNullable(json.config()).map(JSONConfig::getDateFormat).getOrNull());
|
||||
return (TemporalAccessor) converter.convert(deserializeType, value);
|
||||
}
|
||||
|
||||
// TODO JSONArray
|
||||
|
||||
final Class<?> temporalAccessorClass = TypeUtil.getClass(deserializeType);
|
||||
// JSONObject
|
||||
final JSONObject jsonObject = (JSONObject) json;
|
||||
/**
|
||||
* 从JSONObject中获取时间信息,转换为{@link TemporalAccessor}
|
||||
*
|
||||
* @param temporalAccessorClass 目标时间类型
|
||||
* @param jsonObject JSONObject
|
||||
* @return {@link TemporalAccessor}
|
||||
*/
|
||||
private static TemporalAccessor fromJSONObject(final Class<?> temporalAccessorClass, final JSONObject jsonObject) {
|
||||
if (LocalDate.class.equals(temporalAccessorClass) || LocalDateTime.class.equals(temporalAccessorClass)) {
|
||||
// 年
|
||||
final Integer year = jsonObject.getInt(YEAR_KEY);
|
||||
@ -160,6 +208,6 @@ public class TemporalTypeAdapter implements MatcherJSONSerializer<TemporalAccess
|
||||
jsonObject.getInt(NANO_KEY));
|
||||
}
|
||||
|
||||
throw new JSONException("Unsupported type from JSON: {}", deserializeType);
|
||||
throw new JSONException("Unsupported type from JSON {} to {}", jsonObject, temporalAccessorClass);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.lang.tuple.Triple;
|
||||
import org.dromara.hutool.core.reflect.TypeReference;
|
||||
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.JSONDeserializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 三元组反序列化器
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class TripleDeserializer implements JSONDeserializer<Triple<?, ?, ?>> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final TripleDeserializer INSTANCE = new TripleDeserializer();
|
||||
|
||||
@Override
|
||||
public Triple<?, ?, ?> deserialize(final JSON json, Type deserializeType) {
|
||||
if (deserializeType instanceof TypeReference) {
|
||||
deserializeType = ((TypeReference<?>) deserializeType).getType();
|
||||
}
|
||||
final Type leftType = TypeUtil.getTypeArgument(deserializeType, 0);
|
||||
final Type middileType = TypeUtil.getTypeArgument(deserializeType, 1);
|
||||
final Type rightType = TypeUtil.getTypeArgument(deserializeType, 2);
|
||||
|
||||
final JSONObject jsonObject = json.asJSONObject();
|
||||
final JSON left = jsonObject.get("left");
|
||||
final JSON middle = jsonObject.get("middle");
|
||||
final JSON right = jsonObject.get("right");
|
||||
|
||||
return Triple.of(
|
||||
left.toBean(leftType),
|
||||
middle.toBean(middileType),
|
||||
right.toBean(rightType)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.lang.tuple.Tuple;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 多元组Tuple反序列化器
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class TupleDeserializer implements JSONDeserializer<Tuple> {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final TupleDeserializer INSTANCE = new TupleDeserializer();
|
||||
|
||||
@Override
|
||||
public Tuple deserialize(final JSON json, final Type deserializeType) {
|
||||
return Tuple.of(json.toBean(Object[].class));
|
||||
}
|
||||
}
|
@ -20,10 +20,10 @@ import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.text.CharUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.text.escape.EscapeUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONArray;
|
||||
import org.dromara.hutool.json.JSONException;
|
||||
import org.dromara.hutool.json.JSONObject;
|
||||
import org.dromara.hutool.json.JSONUtil;
|
||||
|
||||
/**
|
||||
* JSON转XML字符串工具
|
||||
@ -36,65 +36,61 @@ public class JSONXMLSerializer {
|
||||
* 转换JSONObject为XML
|
||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||
*
|
||||
* @param object A JSONObject.
|
||||
* @param json A JSONObject.
|
||||
* @return A string.
|
||||
* @throws JSONException Thrown if there is an error parsing the string
|
||||
*/
|
||||
public static String toXml(final Object object) throws JSONException {
|
||||
return toXml(object, null);
|
||||
public static String toXml(final JSON json) throws JSONException {
|
||||
return toXml(json, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换JSONObject为XML
|
||||
*
|
||||
* @param object JSON对象或数组
|
||||
* @param json JSON对象或数组
|
||||
* @param tagName 可选标签名称,名称为空时忽略标签
|
||||
* @return A string.
|
||||
* @throws JSONException JSON解析异常
|
||||
*/
|
||||
public static String toXml(final Object object, final String tagName) throws JSONException {
|
||||
return toXml(object, tagName, "content");
|
||||
public static String toXml(final JSON json, final String tagName) throws JSONException {
|
||||
return toXml(json, tagName, "content");
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换JSONObject为XML
|
||||
*
|
||||
* @param object JSON对象或数组
|
||||
* @param json JSON对象或数组
|
||||
* @param tagName 可选标签名称,名称为空时忽略标签
|
||||
* @param contentKeys 标识为内容的key,遇到此key直接解析内容而不增加对应名称标签
|
||||
* @return A string.
|
||||
* @throws JSONException JSON解析异常
|
||||
*/
|
||||
public static String toXml(Object object, final String tagName, final String... contentKeys) throws JSONException {
|
||||
if (null == object) {
|
||||
public static String toXml(JSON json, final String tagName, final String... contentKeys) throws JSONException {
|
||||
if (null == json) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
if (object instanceof JSONObject) {
|
||||
if (json instanceof JSONObject) {
|
||||
|
||||
// Emit <tagName>
|
||||
appendTag(sb, tagName, false);
|
||||
|
||||
// Loop thru the keys.
|
||||
((JSONObject) object).forEach((key, value) -> {
|
||||
if (ArrayUtil.isArray(value)) {
|
||||
value = JSONUtil.parseArray(value);
|
||||
}
|
||||
|
||||
json.asJSONObject().forEach((key, value) -> {
|
||||
// Emit content in body
|
||||
if (ArrayUtil.contains(contentKeys, key)) {
|
||||
if (value instanceof JSONArray) {
|
||||
int i = 0;
|
||||
for (final Object val : (JSONArray) value) {
|
||||
for (final JSON val : (JSONArray) value) {
|
||||
if (i > 0) {
|
||||
sb.append(CharUtil.LF);
|
||||
}
|
||||
sb.append(EscapeUtil.escapeXml(val.toString()));
|
||||
sb.append(EscapeUtil.escapeXml(val.toBean(String.class)));
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
sb.append(EscapeUtil.escapeXml(value.toString()));
|
||||
sb.append(EscapeUtil.escapeXml(value.toBean(String.class)));
|
||||
}
|
||||
|
||||
// Emit an array of similar keys
|
||||
@ -102,7 +98,7 @@ public class JSONXMLSerializer {
|
||||
} else if (StrUtil.isEmptyIfStr(value)) {
|
||||
sb.append(wrapWithTag(null, key));
|
||||
} else if (value instanceof JSONArray) {
|
||||
for (final Object val : (JSONArray) value) {
|
||||
for (final JSON val : (JSONArray) value) {
|
||||
if (val instanceof JSONArray) {
|
||||
sb.append(wrapWithTag(toXml(val, null, contentKeys), key));
|
||||
} else {
|
||||
@ -119,12 +115,8 @@ public class JSONXMLSerializer {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
if (ArrayUtil.isArray(object)) {
|
||||
object = JSONUtil.parseArray(object);
|
||||
}
|
||||
|
||||
if (object instanceof JSONArray) {
|
||||
for (final Object val : (JSONArray) object) {
|
||||
if (json instanceof JSONArray) {
|
||||
for (final JSON val : (JSONArray) json) {
|
||||
// XML does not have good support for arrays. If an array
|
||||
// appears in a place where XML is lacking, synthesize an
|
||||
// <array> element.
|
||||
@ -133,7 +125,7 @@ public class JSONXMLSerializer {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
return wrapWithTag(EscapeUtil.escapeXml(object.toString()), tagName);
|
||||
return wrapWithTag(EscapeUtil.escapeXml(json.toBean(String.class)), tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.dromara.hutool.json.xml;
|
||||
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONException;
|
||||
import org.dromara.hutool.json.JSONObject;
|
||||
|
||||
@ -75,36 +76,36 @@ public class JSONXMLUtil {
|
||||
/**
|
||||
* 转换JSONObject为XML
|
||||
*
|
||||
* @param object JSON对象或数组
|
||||
* @param json JSON对象或数组
|
||||
* @return XML字符串
|
||||
* @throws JSONException JSON解析异常
|
||||
*/
|
||||
public static String toXml(final Object object) throws JSONException {
|
||||
return toXml(object, null);
|
||||
public static String toXml(final JSON json) throws JSONException {
|
||||
return toXml(json, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换JSONObject为XML
|
||||
*
|
||||
* @param object JSON对象或数组
|
||||
* @param json JSON对象或数组
|
||||
* @param tagName 可选标签名称,名称为空时忽略标签
|
||||
* @return A string.
|
||||
* @throws JSONException JSON解析异常
|
||||
*/
|
||||
public static String toXml(final Object object, final String tagName) throws JSONException {
|
||||
return toXml(object, tagName, "content");
|
||||
public static String toXml(final JSON json, final String tagName) throws JSONException {
|
||||
return toXml(json, tagName, "content");
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换JSONObject为XML
|
||||
*
|
||||
* @param object JSON对象或数组
|
||||
* @param json JSON对象或数组
|
||||
* @param tagName 可选标签名称,名称为空时忽略标签
|
||||
* @param contentKeys 标识为内容的key,遇到此key直接解析内容而不增加对应名称标签
|
||||
* @return A string.
|
||||
* @throws JSONException JSON解析异常
|
||||
*/
|
||||
public static String toXml(final Object object, final String tagName, final String... contentKeys) throws JSONException {
|
||||
return JSONXMLSerializer.toXml(object, tagName, contentKeys);
|
||||
public static String toXml(final JSON json, final String tagName, final String... contentKeys) throws JSONException {
|
||||
return JSONXMLSerializer.toXml(json, tagName, contentKeys);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package org.dromara.hutool.json;
|
||||
|
||||
import lombok.ToString;
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.JSONSerializer;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
@ -31,8 +32,13 @@ public class CustomSerializeTest {
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
TypeAdapterManager.getInstance().register(CustomBean.class,
|
||||
(JSONSerializer<CustomBean>) (bean, context) ->
|
||||
((JSONObject)context.getContextJson()).set("customName", bean.name));
|
||||
(JSONSerializer<CustomBean>) (bean, context) ->{
|
||||
JSONObject contextJson = (JSONObject) context.getContextJson();
|
||||
if(null == contextJson){
|
||||
contextJson = JSONUtil.ofObj(context.config());
|
||||
}
|
||||
return contextJson.set("customName", bean.name);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -41,6 +47,7 @@ public class CustomSerializeTest {
|
||||
customBean.name = "testName";
|
||||
|
||||
final JSONObject obj = JSONUtil.parseObj(customBean);
|
||||
Console.log(obj);
|
||||
Assertions.assertEquals("testName", obj.getStr("customName"));
|
||||
}
|
||||
|
||||
|
@ -20,10 +20,7 @@ import lombok.Data;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Month;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* <a href="https://github.com/dromara/hutool/issues/2090">https://github.com/dromara/hutool/issues/2090</a>
|
||||
@ -76,6 +73,23 @@ public class Issue2090Test {
|
||||
final JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.set("month", Month.JANUARY);
|
||||
Assertions.assertEquals("{\"month\":1}", jsonObject.toString());
|
||||
|
||||
final JSON parse = JSONUtil.parse(Month.JANUARY);
|
||||
Assertions.assertInstanceOf(JSONPrimitive.class, parse);
|
||||
Assertions.assertTrue(((JSONPrimitive) parse).isNumber());
|
||||
Assertions.assertEquals("1", parse.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void weekTest(){
|
||||
final JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.set("week", DayOfWeek.SUNDAY);
|
||||
Assertions.assertEquals("{\"week\":7}", jsonObject.toString());
|
||||
|
||||
final JSON parse = JSONUtil.parse(DayOfWeek.SUNDAY);
|
||||
Assertions.assertInstanceOf(JSONPrimitive.class, parse);
|
||||
Assertions.assertTrue(((JSONPrimitive) parse).isNumber());
|
||||
Assertions.assertEquals("7", parse.toString());
|
||||
}
|
||||
|
||||
@Data
|
||||
|
@ -26,10 +26,10 @@ public class Issue2447Test {
|
||||
|
||||
@Test
|
||||
public void addIntegerTest() {
|
||||
Time time = new Time();
|
||||
final Time time = new Time();
|
||||
time.setTime(LocalDateTime.of(1970, 1, 2, 10, 0, 1, 0));
|
||||
String timeStr = JSONUtil.toJsonStr(time);
|
||||
Assertions.assertEquals(timeStr, "{\"time\":93601000}");
|
||||
final String timeStr = JSONUtil.toJsonStr(time);
|
||||
Assertions.assertEquals("{\"time\":93601000}", timeStr);
|
||||
Assertions.assertEquals(JSONUtil.toBean(timeStr, Time.class).getTime(), time.getTime());
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ public class Issue3681Test {
|
||||
Assertions.assertEquals("\"abc\"", abc);
|
||||
|
||||
abc = JSONUtil.toJsonStr(Optional.of("123"));
|
||||
Assertions.assertEquals("123", abc);
|
||||
Assertions.assertEquals("\"123\"", abc);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -45,6 +45,6 @@ public class Issue3681Test {
|
||||
Assertions.assertEquals("\"abc\"", abc);
|
||||
|
||||
abc = JSONUtil.toJsonStr(Opt.of("123"));
|
||||
Assertions.assertEquals("123", abc);
|
||||
Assertions.assertEquals("\"123\"", abc);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package org.dromara.hutool.json;
|
||||
|
||||
import org.dromara.hutool.core.bean.BeanUtil;
|
||||
import lombok.Data;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -31,8 +30,7 @@ public class IssueI3BS4STest {
|
||||
@Test
|
||||
public void toBeanTest(){
|
||||
final String jsonStr = "{date: '2021-03-17T06:31:33.99'}";
|
||||
final Bean1 bean1 = new Bean1();
|
||||
BeanUtil.copyProperties(JSONUtil.parseObj(jsonStr), bean1);
|
||||
final Bean1 bean1 = JSONUtil.parseObj(jsonStr).toBean(Bean1.class);
|
||||
Assertions.assertEquals("2021-03-17T06:31:33.990", bean1.getDate().toString());
|
||||
}
|
||||
|
||||
|
@ -281,7 +281,7 @@ public class JSONArrayTest {
|
||||
.set("value3")
|
||||
.set(true);
|
||||
|
||||
final String s = json1.toJSONString(0, (pair) -> pair.getValue().equals("value2"));
|
||||
final String s = json1.toJSONString(0, (pair) -> ((JSONPrimitive)pair.getValue()).getValue().equals("value2"));
|
||||
assertEquals("[\"value2\"]", s);
|
||||
}
|
||||
|
||||
@ -293,7 +293,7 @@ public class JSONArrayTest {
|
||||
.set("value3")
|
||||
.set(true);
|
||||
|
||||
final String s = json1.toJSONString(0, (pair) -> !pair.getValue().equals("value2"));
|
||||
final String s = json1.toJSONString(0, (pair) -> !((JSONPrimitive)pair.getValue()).getValue().equals("value2"));
|
||||
assertEquals("[\"value1\",\"value3\",true]", s);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import org.dromara.hutool.core.annotation.PropIgnore;
|
||||
import org.dromara.hutool.core.collection.ListUtil;
|
||||
import org.dromara.hutool.core.date.DatePattern;
|
||||
import org.dromara.hutool.core.date.DateUtil;
|
||||
import org.dromara.hutool.core.date.format.GlobalCustomFormat;
|
||||
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
@ -113,7 +114,7 @@ public class JSONObjectTest {
|
||||
@Test
|
||||
public void parseStringTest() {
|
||||
final String jsonStr = "{\"b\":\"value2\",\"c\":\"value3\",\"a\":\"value1\", \"d\": true, \"e\": null}";
|
||||
final JSONObject jsonObject = JSONUtil.parseObj(jsonStr);
|
||||
final JSONObject jsonObject = JSONUtil.parseObj(jsonStr, JSONConfig.of().setIgnoreNullValue(false));
|
||||
assertEquals(jsonObject.getObj("a"), "value1");
|
||||
assertEquals(jsonObject.getObj("b"), "value2");
|
||||
assertEquals(jsonObject.getObj("c"), "value3");
|
||||
@ -226,6 +227,13 @@ public class JSONObjectTest {
|
||||
assertNull(bean.getBeanValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void addListTest(){
|
||||
final JSONObject json = JSONUtil.ofObj();
|
||||
json.set("list", ListUtil.of(1, 2, 3));
|
||||
Assertions.assertEquals("{\"list\":[1,2,3]}", json.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBeanTest2() {
|
||||
final UserA userA = new UserA();
|
||||
@ -245,7 +253,7 @@ public class JSONObjectTest {
|
||||
@Test
|
||||
public void toBeanWithNullTest() {
|
||||
final String jsonStr = "{'data':{'userName':'ak','password': null}}";
|
||||
final UserWithMap user = JSONUtil.toBean(JSONUtil.parseObj(jsonStr), UserWithMap.class);
|
||||
final UserWithMap user = JSONUtil.toBean(JSONUtil.parseObj(jsonStr, JSONConfig.of().setIgnoreNullValue(false)), UserWithMap.class);
|
||||
Assertions.assertTrue(user.getData().containsKey("password"));
|
||||
}
|
||||
|
||||
@ -323,7 +331,7 @@ public class JSONObjectTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseBeanTest2() {
|
||||
public void parseBeanWithNumberListEnumTest() {
|
||||
final TestBean bean = new TestBean();
|
||||
bean.setDoubleValue(111.1);
|
||||
bean.setIntValue(123);
|
||||
@ -333,8 +341,10 @@ public class JSONObjectTest {
|
||||
|
||||
final JSONObject json = JSONUtil.parseObj(bean,
|
||||
JSONConfig.of().setIgnoreNullValue(false));
|
||||
// 枚举转换检查,更新:枚举原样保存,在writer时调用toString。
|
||||
assertEquals(TestEnum.TYPE_B, json.getObj("testEnum"));
|
||||
|
||||
assertEquals(111.1, json.getObj("doubleValue"));
|
||||
// 枚举转换检查,默认序列化枚举为其name
|
||||
assertEquals(TestEnum.TYPE_B.name(), json.getObj("testEnum"));
|
||||
|
||||
final TestBean bean2 = json.toBean(TestBean.class);
|
||||
assertEquals(bean.toString(), bean2.toString());
|
||||
@ -479,9 +489,9 @@ public class JSONObjectTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDateFormatTest3() {
|
||||
public void setDateFormatSecondsTest() {
|
||||
// 自定义格式为只有秒的时间戳,一般用于JWT
|
||||
final JSONConfig jsonConfig = JSONConfig.of().setDateFormat("#sss");
|
||||
final JSONConfig jsonConfig = JSONConfig.of().setDateFormat(GlobalCustomFormat.FORMAT_SECONDS);
|
||||
|
||||
final Date date = DateUtil.parse("2020-06-05 11:16:11");
|
||||
final JSONObject json = new JSONObject(jsonConfig);
|
||||
@ -497,7 +507,7 @@ public class JSONObjectTest {
|
||||
@Test
|
||||
public void setCustomDateFormatTest() {
|
||||
final JSONConfig jsonConfig = JSONConfig.of();
|
||||
jsonConfig.setDateFormat("#sss");
|
||||
jsonConfig.setDateFormat(GlobalCustomFormat.FORMAT_SECONDS);
|
||||
|
||||
final Date date = DateUtil.parse("2020-06-05 11:16:11");
|
||||
final JSONObject json = new JSONObject(jsonConfig);
|
||||
@ -609,7 +619,7 @@ public class JSONObjectTest {
|
||||
|
||||
@Test
|
||||
public void createJSONObjectTest() {
|
||||
Assertions.assertThrows(JSONException.class, ()->{
|
||||
Assertions.assertThrows(ClassCastException.class, ()->{
|
||||
// 集合类不支持转为JSONObject
|
||||
JSONUtil.parseObj(new JSONArray(), JSONConfig.of());
|
||||
});
|
||||
@ -692,7 +702,8 @@ public class JSONObjectTest {
|
||||
final String s = json1.toJSONString(0, (pair) -> {
|
||||
if ("b".equals(pair.getKey())) {
|
||||
// 修改值为新值
|
||||
pair.setValue(pair.getValue() + "_edit");
|
||||
final JSONPrimitive value = (JSONPrimitive) pair.getValue();
|
||||
pair.setValue(value.getValue() + "_edit");
|
||||
return true;
|
||||
}
|
||||
// 除了"b",其他都去掉
|
||||
|
@ -102,7 +102,7 @@ public class JSONUtilTest {
|
||||
*/
|
||||
@Test
|
||||
public void parseNumberToJSONArrayTest() {
|
||||
assertThrows(JSONException.class, () -> {
|
||||
assertThrows(ClassCastException.class, () -> {
|
||||
final JSONArray json = JSONUtil.parseArray(123L);
|
||||
Assertions.assertNotNull(json);
|
||||
});
|
||||
|
@ -31,7 +31,7 @@ public class JSONWriterTest {
|
||||
|
||||
// 日期原样写入
|
||||
final Date date = jsonObject.getDate("date");
|
||||
Assertions.assertEquals("2022-09-30 00:00:00", date.toString());
|
||||
Assertions.assertEquals("2022-09-30 00:00:00", DateUtil.date(date).toString());
|
||||
|
||||
// 自定义日期格式生效
|
||||
Assertions.assertEquals("{\"date\":\"2022-09-30\"}", jsonObject.toString());
|
||||
|
@ -161,7 +161,7 @@ public class JWTTest {
|
||||
Assertions.assertEquals(bean, beanRes);
|
||||
Assertions.assertEquals(numRes, num);
|
||||
Assertions.assertEquals(username, strRes);
|
||||
Assertions.assertEquals(list, listRes);
|
||||
Assertions.assertEquals(list.toString(), listRes.toString());
|
||||
|
||||
final String formattedDate = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
|
||||
final String formattedRes = DateUtil.format(dateRes, "yyyy-MM-dd HH:mm:ss");
|
||||
|
@ -39,7 +39,7 @@ public class XMLTest {
|
||||
|
||||
Assertions.assertEquals("{\"a\":\"•\"}", jsonObject.toString());
|
||||
|
||||
final String xml2 = JSONXMLUtil.toXml(JSONUtil.parseObj(jsonObject));
|
||||
final String xml2 = JSONXMLUtil.toXml(jsonObject);
|
||||
Assertions.assertEquals(xml, xml2);
|
||||
}
|
||||
|
||||
@ -53,4 +53,11 @@ public class XMLTest {
|
||||
xml = JSONXMLUtil.toXml(jsonObject, null, new String[0]);
|
||||
Assertions.assertEquals("<content>123456</content>", xml);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlContentTest2(){
|
||||
final JSONObject jsonObject = JSONUtil.ofObj().set("content","123456");
|
||||
final String xml = JSONXMLUtil.toXml(jsonObject, null, new String[0]);
|
||||
Assertions.assertEquals("<content>123456</content>", xml);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user