This commit is contained in:
Looly 2024-08-03 12:40:38 +08:00
parent e487d924cb
commit 7f60318dd8
19 changed files with 286 additions and 170 deletions

View File

@ -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

View File

@ -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);

View File

@ -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 {
// nullJSON字符串和自定义对象原样存储 // nullJSON字符串和自定义对象原样存储
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);

View File

@ -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());
} }
} }

View File

@ -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());
}
}

View File

@ -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());

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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());
} }

View File

@ -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());
}
}

View File

@ -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();

View File

@ -25,7 +25,7 @@ public enum NumberWriteMode {
*/ */
NORMAL, NORMAL,
/** /**
* 浏览器中Javascript兼容模式此模式下如果Long输出长度大于 * 浏览器中Javascript兼容模式此模式下如果Long输出长度大于JS中最大长度则转为字符串形式
*/ */
JS, JS,
/** /**

View File

@ -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());
}
}

View File

@ -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);
} }

View File

@ -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());

View File

@ -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());
}
}

View File

@ -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