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
e487d924cb
commit
7f60318dd8
@ -29,8 +29,6 @@ import org.dromara.hutool.core.text.split.SplitUtil;
|
|||||||
import org.dromara.hutool.json.serialize.GlobalSerializeMapping;
|
import org.dromara.hutool.json.serialize.GlobalSerializeMapping;
|
||||||
import org.dromara.hutool.json.serialize.JSONDeserializer;
|
import org.dromara.hutool.json.serialize.JSONDeserializer;
|
||||||
import org.dromara.hutool.json.serialize.JSONStringer;
|
import org.dromara.hutool.json.serialize.JSONStringer;
|
||||||
import org.dromara.hutool.json.writer.GlobalValueWriterMapping;
|
|
||||||
import org.dromara.hutool.json.writer.JSONValueWriter;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
@ -262,23 +260,6 @@ public final class InternalJSONUtil {
|
|||||||
return rawHashMap;
|
return rawHashMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据值类型获取{@link JSONValueWriter},首先判断对象是否实现了{@link JSONValueWriter}接口<br>
|
|
||||||
* 如果未实现从{@link GlobalValueWriterMapping}中查找全局的writer,否则返回null。
|
|
||||||
*
|
|
||||||
* @param value 值
|
|
||||||
* @param <T> 值类型
|
|
||||||
* @return {@link JSONValueWriter}
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T> JSONValueWriter<T> getValueWriter(final T value) {
|
|
||||||
if (value instanceof JSONValueWriter) {
|
|
||||||
return (JSONValueWriter<T>) value;
|
|
||||||
}
|
|
||||||
// 全局自定义序列化,支持null的自定义写出
|
|
||||||
return (JSONValueWriter<T>) GlobalValueWriterMapping.get(null == value ? null : value.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据目标类型,获取对应的{@link JSONDeserializer},首先判断是否实现了{@link JSONDeserializer}接口<br>
|
* 根据目标类型,获取对应的{@link JSONDeserializer},首先判断是否实现了{@link JSONDeserializer}接口<br>
|
||||||
* 如果未实现从{@link GlobalSerializeMapping}中查找全局的{@link JSONDeserializer},否则返回null
|
* 如果未实现从{@link GlobalSerializeMapping}中查找全局的{@link JSONDeserializer},否则返回null
|
||||||
|
@ -24,6 +24,7 @@ import org.dromara.hutool.json.serialize.GlobalSerializeMapping;
|
|||||||
import org.dromara.hutool.json.serialize.JSONArraySerializer;
|
import org.dromara.hutool.json.serialize.JSONArraySerializer;
|
||||||
import org.dromara.hutool.json.serialize.JSONDeserializer;
|
import org.dromara.hutool.json.serialize.JSONDeserializer;
|
||||||
import org.dromara.hutool.json.serialize.JSONObjectSerializer;
|
import org.dromara.hutool.json.serialize.JSONObjectSerializer;
|
||||||
|
import org.dromara.hutool.json.writer.GlobalValueWriters;
|
||||||
import org.dromara.hutool.json.writer.JSONValueWriter;
|
import org.dromara.hutool.json.writer.JSONValueWriter;
|
||||||
import org.dromara.hutool.json.writer.JSONWriter;
|
import org.dromara.hutool.json.writer.JSONWriter;
|
||||||
import org.dromara.hutool.json.xml.JSONXMLUtil;
|
import org.dromara.hutool.json.xml.JSONXMLUtil;
|
||||||
@ -264,10 +265,9 @@ public class JSONUtil {
|
|||||||
* @return JSON字符串
|
* @return JSON字符串
|
||||||
* @since 5.7.12
|
* @since 5.7.12
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
||||||
public static String toJsonStr(final Object obj, final JSONConfig jsonConfig) {
|
public static String toJsonStr(final Object obj, final JSONConfig jsonConfig) {
|
||||||
// 自定义规则,优先级高于全局规则
|
// 自定义规则,优先级高于全局规则
|
||||||
final JSONValueWriter valueWriter = InternalJSONUtil.getValueWriter(obj);
|
final JSONValueWriter valueWriter = GlobalValueWriters.get(obj);
|
||||||
if (null != valueWriter) {
|
if (null != valueWriter) {
|
||||||
final StringWriter stringWriter = new StringWriter();
|
final StringWriter stringWriter = new StringWriter();
|
||||||
final JSONWriter jsonWriter = JSONWriter.of(stringWriter, 0, 0, null);
|
final JSONWriter jsonWriter = JSONWriter.of(stringWriter, 0, 0, null);
|
||||||
|
@ -13,19 +13,16 @@
|
|||||||
package org.dromara.hutool.json.mapper;
|
package org.dromara.hutool.json.mapper;
|
||||||
|
|
||||||
import org.dromara.hutool.core.array.ArrayUtil;
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
import org.dromara.hutool.core.math.NumberUtil;
|
|
||||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
import org.dromara.hutool.core.util.ObjUtil;
|
import org.dromara.hutool.core.util.ObjUtil;
|
||||||
import org.dromara.hutool.json.*;
|
import org.dromara.hutool.json.JSON;
|
||||||
|
import org.dromara.hutool.json.JSONArray;
|
||||||
|
import org.dromara.hutool.json.JSONConfig;
|
||||||
|
import org.dromara.hutool.json.JSONObject;
|
||||||
import org.dromara.hutool.json.serialize.JSONStringer;
|
import org.dromara.hutool.json.serialize.JSONStringer;
|
||||||
|
import org.dromara.hutool.json.writer.GlobalValueWriters;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.time.temporal.TemporalAccessor;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对象和JSON值映射器,用于转换对象为JSON对象中的值<br>
|
* 对象和JSON值映射器,用于转换对象为JSON对象中的值<br>
|
||||||
@ -129,7 +126,7 @@ public class JSONValueMapper {
|
|||||||
// null、JSON、字符串和自定义对象原样存储
|
// null、JSON、字符串和自定义对象原样存储
|
||||||
if (null == object
|
if (null == object
|
||||||
// 当用户自定义了对象的字符串表示形式,则保留这个对象
|
// 当用户自定义了对象的字符串表示形式,则保留这个对象
|
||||||
|| null != InternalJSONUtil.getValueWriter(object)
|
|| null != GlobalValueWriters.get(object)
|
||||||
|| object instanceof JSON //
|
|| object instanceof JSON //
|
||||||
|| object instanceof JSONStringer //
|
|| object instanceof JSONStringer //
|
||||||
|| object instanceof CharSequence //
|
|| object instanceof CharSequence //
|
||||||
@ -138,53 +135,12 @@ public class JSONValueMapper {
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 合法数字原样存储
|
|
||||||
if(object instanceof Number){
|
|
||||||
if(!NumberUtil.isValidNumber((Number) object)){
|
|
||||||
throw new JSONException("JSON does not allow non-finite numbers.");
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 日期类型做包装,以便自定义输出格式
|
|
||||||
if (object instanceof Date
|
|
||||||
|| object instanceof Calendar
|
|
||||||
|| object instanceof TemporalAccessor
|
|
||||||
) {
|
|
||||||
// 日期类型保存原始类型,用于在writer时自定义转字符串
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 特定对象转换
|
// 特定对象转换
|
||||||
try {
|
try {
|
||||||
// fix issue#1399@Github
|
|
||||||
if (object instanceof SQLException
|
|
||||||
) {
|
|
||||||
return object.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSONArray
|
// JSONArray
|
||||||
if (object instanceof Iterable || ArrayUtil.isArray(object)) {
|
if (object instanceof Iterable || ArrayUtil.isArray(object)) {
|
||||||
return new JSONArray(object, jsonConfig);
|
return new JSONArray(object, jsonConfig);
|
||||||
}
|
}
|
||||||
// JSONObject
|
|
||||||
if (object instanceof Map || object instanceof Map.Entry) {
|
|
||||||
return new JSONObject(object, jsonConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
// pr#3507
|
|
||||||
// Class类型保存类名
|
|
||||||
if (object instanceof Class) {
|
|
||||||
return ((Class<?>) object).getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 枚举类保存其字符串形式(4.0.2新增)
|
|
||||||
if (object instanceof Enum
|
|
||||||
// Java内部类不做转换
|
|
||||||
|| ClassUtil.isJdkClass(object.getClass())
|
|
||||||
) {
|
|
||||||
return object.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 默认按照JSONObject对待
|
// 默认按照JSONObject对待
|
||||||
return new JSONObject(object, jsonConfig);
|
return new JSONObject(object, jsonConfig);
|
||||||
|
@ -18,14 +18,19 @@ package org.dromara.hutool.json.writer;
|
|||||||
* @author looly
|
* @author looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class BooleanValueWriter implements JSONValueWriter<Boolean> {
|
public class BooleanValueWriter implements JSONValueWriter {
|
||||||
/**
|
/**
|
||||||
* 单例对象
|
* 单例对象
|
||||||
*/
|
*/
|
||||||
public static final BooleanValueWriter INSTANCE = new BooleanValueWriter();
|
public static final BooleanValueWriter INSTANCE = new BooleanValueWriter();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(final JSONWriter writer, final Boolean bool) {
|
public boolean test(final Object bool) {
|
||||||
|
return bool instanceof Boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(final JSONWriter writer, final Object bool) {
|
||||||
writer.writeRaw(bool.toString());
|
writer.writeRaw(bool.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2024. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.json.writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Class}类型的值写出器
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 6.0.0
|
||||||
|
*/
|
||||||
|
public class ClassValueWriter implements JSONValueWriter {
|
||||||
|
/**
|
||||||
|
* 单例对象
|
||||||
|
*/
|
||||||
|
public static final ClassValueWriter INSTANCE = new ClassValueWriter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(final Object value) {
|
||||||
|
return value instanceof Class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(final JSONWriter writer, final Object value) {
|
||||||
|
writer.writeQuoteStrValue(((Class<?>) value).getName());
|
||||||
|
}
|
||||||
|
}
|
@ -25,12 +25,17 @@ import java.util.Date;
|
|||||||
* @author looly
|
* @author looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class DateValueWriter implements JSONValueWriter<Object> {
|
public class DateValueWriter implements JSONValueWriter {
|
||||||
/**
|
/**
|
||||||
* 单例对象
|
* 单例对象
|
||||||
*/
|
*/
|
||||||
public static final DateValueWriter INSTANCE = new DateValueWriter();
|
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
|
@Override
|
||||||
public void write(final JSONWriter writer, final Object value) {
|
public void write(final JSONWriter writer, final Object value) {
|
||||||
writer.writeRaw(new DateJSONString(value, writer.getConfig()).toJSONString());
|
writer.writeRaw(new DateJSONString(value, writer.getConfig()).toJSONString());
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
|
||||||
* Hutool is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* https://license.coscl.org.cn/MulanPSL2
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.dromara.hutool.json.writer;
|
|
||||||
|
|
||||||
import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap;
|
|
||||||
import org.dromara.hutool.core.reflect.NullType;
|
|
||||||
import org.dromara.hutool.core.util.ObjUtil;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局自定义对象写出<br>
|
|
||||||
* 用户通过此全局定义,可针对某些特殊对象
|
|
||||||
*
|
|
||||||
* @author looly
|
|
||||||
* @since 6.0.0
|
|
||||||
*/
|
|
||||||
public class GlobalValueWriterMapping {
|
|
||||||
|
|
||||||
private static final Map<Type, JSONValueWriter<?>> writerMap;
|
|
||||||
|
|
||||||
static {
|
|
||||||
writerMap = new SafeConcurrentHashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加入自定义的对象值写出规则
|
|
||||||
*
|
|
||||||
* @param type 对象类型
|
|
||||||
* @param writer 自定义对象写出实现
|
|
||||||
*/
|
|
||||||
public static void put(final Type type, final JSONValueWriter<?> writer) {
|
|
||||||
writerMap.put(ObjUtil.defaultIfNull(type, NullType.INSTANCE), writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取自定义对象值写出规则
|
|
||||||
*
|
|
||||||
* @param type 对象类型
|
|
||||||
* @return 自定义的 {@link JSONValueWriter}
|
|
||||||
*/
|
|
||||||
public static JSONValueWriter<?> get(final Type type) {
|
|
||||||
return writerMap.get(ObjUtil.defaultIfNull(type, NullType.INSTANCE));
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.json.writer;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局自定义对象写出<br>
|
||||||
|
* 用户通过此全局定义,可针对某些特殊对象
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 6.0.0
|
||||||
|
*/
|
||||||
|
public class GlobalValueWriters {
|
||||||
|
|
||||||
|
private static final List<JSONValueWriter> valueWriterList;
|
||||||
|
|
||||||
|
static {
|
||||||
|
valueWriterList = Collections.synchronizedList(new LinkedList<>());
|
||||||
|
valueWriterList.add(NumberValueWriter.INSTANCE);
|
||||||
|
valueWriterList.add(DateValueWriter.INSTANCE);
|
||||||
|
valueWriterList.add(BooleanValueWriter.INSTANCE);
|
||||||
|
valueWriterList.add(JSONStringValueWriter.INSTANCE);
|
||||||
|
valueWriterList.add(ClassValueWriter.INSTANCE);
|
||||||
|
valueWriterList.add(JdkValueWriter.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加入自定义的对象值写出规则,自定义规则总是优先
|
||||||
|
*
|
||||||
|
* @param valueWriter 自定义对象写出实现
|
||||||
|
*/
|
||||||
|
public static void add(final JSONValueWriter valueWriter) {
|
||||||
|
valueWriterList.add(0, Assert.notNull(valueWriter));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取自定义对象值写出规则
|
||||||
|
*
|
||||||
|
* @param value 值,{@code null}表示需要自定义null的输出
|
||||||
|
* @return 自定义的 {@link JSONValueWriter}
|
||||||
|
*/
|
||||||
|
public static JSONValueWriter get(final Object value) {
|
||||||
|
if (value instanceof JSONValueWriter) {
|
||||||
|
return (JSONValueWriter) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return valueWriterList.stream().filter(writer -> writer.test(value)).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
}
|
@ -15,23 +15,23 @@ package org.dromara.hutool.json.writer;
|
|||||||
import org.dromara.hutool.json.JSONException;
|
import org.dromara.hutool.json.JSONException;
|
||||||
import org.dromara.hutool.json.serialize.JSONStringer;
|
import org.dromara.hutool.json.serialize.JSONStringer;
|
||||||
|
|
||||||
import java.time.temporal.TemporalAccessor;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日期类型的值写出器<br>
|
* {@link JSONStringer}的值写出器
|
||||||
* 支持包括:{@link Date}、{@link Calendar}、{@link TemporalAccessor}
|
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class JSONStringValueWriter implements JSONValueWriter<JSONStringer> {
|
public class JSONStringValueWriter implements JSONValueWriter {
|
||||||
/**
|
/**
|
||||||
* 单例对象
|
* 单例对象
|
||||||
*/
|
*/
|
||||||
public static final JSONStringValueWriter INSTANCE = new JSONStringValueWriter();
|
public static final JSONStringValueWriter INSTANCE = new JSONStringValueWriter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(final Object value) {
|
||||||
|
return value instanceof JSONStringer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输出实现了{@link JSONStringer}接口的对象,通过调用{@link JSONStringer#toJSONString()}获取JSON字符串<br>
|
* 输出实现了{@link JSONStringer}接口的对象,通过调用{@link JSONStringer#toJSONString()}获取JSON字符串<br>
|
||||||
* {@link JSONStringer}按照JSON对象对待,此方法输出的JSON字符串不包装引号。<br>
|
* {@link JSONStringer}按照JSON对象对待,此方法输出的JSON字符串不包装引号。<br>
|
||||||
@ -41,10 +41,10 @@ public class JSONStringValueWriter implements JSONValueWriter<JSONStringer> {
|
|||||||
* @param jsonStringer {@link JSONStringer}
|
* @param jsonStringer {@link JSONStringer}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(final JSONWriter writer, final JSONStringer jsonStringer) {
|
public void write(final JSONWriter writer, final Object jsonStringer) {
|
||||||
final String valueStr;
|
final String valueStr;
|
||||||
try {
|
try {
|
||||||
valueStr = jsonStringer.toJSONString();
|
valueStr = ((JSONStringer)jsonStringer).toJSONString();
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
throw new JSONException(e);
|
throw new JSONException(e);
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,32 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.json.writer;
|
package org.dromara.hutool.json.writer;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON的值自定义写出
|
* JSON的值自定义写出,通过自定义实现此接口,实现对象自定义写出字符串形式<br>
|
||||||
|
* 如自定义的一个CustomBean,我只希望输出id的值,此时自定义此接口:
|
||||||
|
* <pre>{@code
|
||||||
|
* GlobalValueWriters.add(new JSONValueWriter() {
|
||||||
|
* @Override
|
||||||
|
* public boolean test(final Object value) {
|
||||||
|
* return value instanceof CustomBean;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
* public void write(final JSONWriter writer, final Object value) {
|
||||||
|
* writer.writeRaw(String.valueOf(((CustomBean)value).getId()));
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* 其中{@link JSONValueWriter#test(Object)}负责判断何种对象使用此规则,{@link JSONValueWriter#write(JSONWriter, Object)}负责写出规则。<br>
|
||||||
|
* 注意:使用{@link GlobalValueWriters#add(JSONValueWriter)}加入全局转换规则后,在JSON对象中,自定义对象不会被转换,而是原始对象存在。
|
||||||
*
|
*
|
||||||
* @param <T> 写出的对象类型
|
|
||||||
* @author looly
|
* @author looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public interface JSONValueWriter<T> {
|
public interface JSONValueWriter extends Predicate<Object> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用{@link JSONWriter} 写出对象
|
* 使用{@link JSONWriter} 写出对象
|
||||||
@ -27,5 +45,5 @@ public interface JSONValueWriter<T> {
|
|||||||
* @param writer {@link JSONWriter}
|
* @param writer {@link JSONWriter}
|
||||||
* @param value 被写出的值
|
* @param value 被写出的值
|
||||||
*/
|
*/
|
||||||
void write(JSONWriter writer, T value);
|
void write(JSONWriter writer, Object value);
|
||||||
}
|
}
|
||||||
|
@ -14,19 +14,15 @@ package org.dromara.hutool.json.writer;
|
|||||||
|
|
||||||
import org.dromara.hutool.core.io.IORuntimeException;
|
import org.dromara.hutool.core.io.IORuntimeException;
|
||||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
import org.dromara.hutool.core.text.CharUtil;
|
import org.dromara.hutool.core.text.CharUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
import org.dromara.hutool.core.util.ObjUtil;
|
import org.dromara.hutool.core.util.ObjUtil;
|
||||||
import org.dromara.hutool.json.InternalJSONUtil;
|
import org.dromara.hutool.json.InternalJSONUtil;
|
||||||
import org.dromara.hutool.json.JSON;
|
import org.dromara.hutool.json.JSON;
|
||||||
import org.dromara.hutool.json.JSONConfig;
|
import org.dromara.hutool.json.JSONConfig;
|
||||||
import org.dromara.hutool.json.serialize.JSONStringer;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.time.temporal.TemporalAccessor;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -311,30 +307,22 @@ public class JSONWriter extends Writer {
|
|||||||
* @param predicate 过滤修改器
|
* @param predicate 过滤修改器
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings("resource")
|
||||||
private JSONWriter writeObjValue(final Object value, final Predicate<MutableEntry<Object, Object>> predicate) {
|
private JSONWriter writeObjValue(final Object value, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||||
final int indent = indentFactor + this.indent;
|
final int indent = indentFactor + this.indent;
|
||||||
|
|
||||||
// 自定义规则
|
// 自定义规则
|
||||||
final JSONValueWriter valueWriter = InternalJSONUtil.getValueWriter(value);
|
final JSONValueWriter valueWriter = GlobalValueWriters.get(value);
|
||||||
if(null != valueWriter){
|
if(null != valueWriter){
|
||||||
valueWriter.write(this, value);
|
valueWriter.write(this, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认规则
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
//noinspection resource
|
|
||||||
writeRaw(StrUtil.NULL);
|
writeRaw(StrUtil.NULL);
|
||||||
}else if (value instanceof JSON) {
|
}else if (value instanceof JSON) {
|
||||||
((JSON) value).write(writer, indentFactor, indent, predicate);
|
((JSON) value).write(writer, indentFactor, indent, predicate);
|
||||||
} else if (value instanceof Number) {
|
|
||||||
NumberValueWriter.INSTANCE.write(this, (Number) value);
|
|
||||||
} else if (value instanceof Date || value instanceof Calendar || value instanceof TemporalAccessor) {
|
|
||||||
DateValueWriter.INSTANCE.write(this, value);
|
|
||||||
} else if (value instanceof Boolean) {
|
|
||||||
BooleanValueWriter.INSTANCE.write(this, (Boolean) value);
|
|
||||||
} else if (value instanceof JSONStringer) {
|
|
||||||
JSONStringValueWriter.INSTANCE.write(this, (JSONStringer) value);
|
|
||||||
} else {
|
} else {
|
||||||
writeQuoteStrValue(value.toString());
|
writeQuoteStrValue(value.toString());
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.json.writer;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
|
import org.dromara.hutool.core.reflect.ClassUtil;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
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 JSONValueWriter {
|
||||||
|
/**
|
||||||
|
* 单例对象
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可转换为JSONObject和JSONArray的对象
|
||||||
|
if (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) {
|
||||||
|
writer.writeQuoteStrValue(value.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ package org.dromara.hutool.json.writer;
|
|||||||
|
|
||||||
import org.dromara.hutool.core.math.NumberUtil;
|
import org.dromara.hutool.core.math.NumberUtil;
|
||||||
import org.dromara.hutool.json.JSONConfig;
|
import org.dromara.hutool.json.JSONConfig;
|
||||||
|
import org.dromara.hutool.json.JSONException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数字类型的值写出器
|
* 数字类型的值写出器
|
||||||
@ -21,7 +22,7 @@ import org.dromara.hutool.json.JSONConfig;
|
|||||||
* @author looly
|
* @author looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class NumberValueWriter implements JSONValueWriter<Number> {
|
public class NumberValueWriter implements JSONValueWriter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JS中表示的数字最大值
|
* JS中表示的数字最大值
|
||||||
@ -33,19 +34,32 @@ public class NumberValueWriter implements JSONValueWriter<Number> {
|
|||||||
*/
|
*/
|
||||||
public static final NumberValueWriter INSTANCE = new NumberValueWriter();
|
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>
|
* 写出数字,根据{@link JSONConfig#isStripTrailingZeros()} 配置不同,写出不同数字<br>
|
||||||
* 主要针对Double型是否去掉小数点后多余的0<br>
|
* 主要针对Double型是否去掉小数点后多余的0<br>
|
||||||
* 此方法输出的值不包装引号。
|
* 此方法输出的值不包装引号。
|
||||||
*
|
*
|
||||||
* @param writer {@link JSONWriter}
|
* @param writer {@link JSONWriter}
|
||||||
* @param number 数字
|
* @param value 数字
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(final JSONWriter writer, final Number number) {
|
public void write(final JSONWriter writer, final Object value) {
|
||||||
final JSONConfig config = writer.getConfig();
|
final JSONConfig config = writer.getConfig();
|
||||||
// since 5.6.2可配置是否去除末尾多余0,例如如果为true,5.0返回5
|
// since 5.6.2可配置是否去除末尾多余0,例如如果为true,5.0返回5
|
||||||
final boolean isStripTrailingZeros = (null == config) || config.isStripTrailingZeros();
|
final boolean isStripTrailingZeros = (null == config) || config.isStripTrailingZeros();
|
||||||
|
final Number number = (Number) value;
|
||||||
final String numberStr = NumberUtil.toStr(number, isStripTrailingZeros);
|
final String numberStr = NumberUtil.toStr(number, isStripTrailingZeros);
|
||||||
|
|
||||||
final NumberWriteMode numberWriteMode = (null == config) ? NumberWriteMode.NORMAL : config.getNumberWriteMode();
|
final NumberWriteMode numberWriteMode = (null == config) ? NumberWriteMode.NORMAL : config.getNumberWriteMode();
|
||||||
|
@ -25,7 +25,7 @@ public enum NumberWriteMode {
|
|||||||
*/
|
*/
|
||||||
NORMAL,
|
NORMAL,
|
||||||
/**
|
/**
|
||||||
* 浏览器中Javascript兼容模式,此模式下,如果Long输出长度大于
|
* 浏览器中Javascript兼容模式,此模式下,如果Long输出长度大于JS中最大长度,则转为字符串形式
|
||||||
*/
|
*/
|
||||||
JS,
|
JS,
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package org.dromara.hutool.json;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/dromara/hutool/issues/1399<br>
|
||||||
|
* 异常SQLException实现了Iterable导致被识别为列表,可能造成死循环,此处按照字符串处理
|
||||||
|
*/
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.json;
|
package org.dromara.hutool.json;
|
||||||
|
|
||||||
import org.dromara.hutool.core.lang.Console;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -33,7 +32,6 @@ public class Issue2090Test {
|
|||||||
test.setLocalDate(LocalDate.now());
|
test.setLocalDate(LocalDate.now());
|
||||||
|
|
||||||
final JSONObject json = JSONUtil.parseObj(test);
|
final JSONObject json = JSONUtil.parseObj(test);
|
||||||
Console.log(json);
|
|
||||||
final TestBean test1 = json.toBean(TestBean.class);
|
final TestBean test1 = json.toBean(TestBean.class);
|
||||||
Assertions.assertEquals(test, test1);
|
Assertions.assertEquals(test, test1);
|
||||||
}
|
}
|
||||||
|
@ -337,8 +337,8 @@ public class JSONObjectTest {
|
|||||||
bean.setTestEnum(TestEnum.TYPE_B);
|
bean.setTestEnum(TestEnum.TYPE_B);
|
||||||
|
|
||||||
final JSONObject json = JSONUtil.parseObj(bean, false);
|
final JSONObject json = JSONUtil.parseObj(bean, false);
|
||||||
// 枚举转换检查
|
// 枚举转换检查,更新:枚举原样保存,在writer时调用toString。
|
||||||
Assertions.assertEquals("TYPE_B", json.get("testEnum"));
|
Assertions.assertEquals(TestEnum.TYPE_B, json.get("testEnum"));
|
||||||
|
|
||||||
final TestBean bean2 = json.toBean(TestBean.class);
|
final TestBean bean2 = json.toBean(TestBean.class);
|
||||||
Assertions.assertEquals(bean.toString(), bean2.toString());
|
Assertions.assertEquals(bean.toString(), bean2.toString());
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package org.dromara.hutool.json;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class Pr3507Test {
|
||||||
|
@Test
|
||||||
|
void writeClassTest() {
|
||||||
|
final JSONObject set = JSONUtil.ofObj().set("name", Pr3507Test.class);
|
||||||
|
Assertions.assertEquals("{\"name\":\"org.dromara.hutool.json.Pr3507Test\"}", set.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -20,12 +20,21 @@ import org.junit.jupiter.api.Assertions;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class GlobalValueWriterMappingTest {
|
public class GlobalValueWritersTest {
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void init(){
|
public void init(){
|
||||||
GlobalValueWriterMapping.put(CustomSubBean.class,
|
GlobalValueWriters.add(new JSONValueWriter() {
|
||||||
(JSONValueWriter<CustomSubBean>) (writer, value) -> writer.writeRaw(String.valueOf(value.getId())));
|
@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
|
@Test
|
Loading…
x
Reference in New Issue
Block a user