diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/InternalJSONUtil.java b/hutool-json/src/main/java/org/dromara/hutool/json/InternalJSONUtil.java
index fccfef873..cbc15f16d 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/InternalJSONUtil.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/InternalJSONUtil.java
@@ -24,8 +24,8 @@ import org.dromara.hutool.core.map.CaseInsensitiveTreeMap;
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.json.serializer.JSONMapper;
import org.dromara.hutool.json.reader.JSONTokener;
+import org.dromara.hutool.json.serializer.JSONMapper;
import java.io.IOException;
import java.math.BigDecimal;
@@ -102,8 +102,8 @@ public final class InternalJSONUtil {
*/
static boolean defaultIgnoreNullValue(final Object obj) {
return (!(obj instanceof CharSequence))//
- && (!(obj instanceof JSONTokener))//
- && (!(obj instanceof Map));
+ && (!(obj instanceof JSONTokener))//
+ && (!(obj instanceof Map));
}
/**
@@ -114,12 +114,13 @@ public final class InternalJSONUtil {
* @since 5.8.0
*/
public static CopyOptions toCopyOptions(final JSONConfig config) {
+ final JSONMapper mapper = JSONFactory.of(config, null).getMapper();
return CopyOptions.of()
- .setIgnoreCase(config.isIgnoreCase())
- .setIgnoreError(config.isIgnoreError())
- .setIgnoreNullValue(config.isIgnoreNullValue())
- .setTransientSupport(config.isTransientSupport())
- .setConverter((targetType, value) -> JSONMapper.of(config, null).map(value));
+ .setIgnoreCase(config.isIgnoreCase())
+ .setIgnoreError(config.isIgnoreError())
+ .setIgnoreNullValue(config.isIgnoreNullValue())
+ .setTransientSupport(config.isTransientSupport())
+ .setConverter((targetType, value) -> mapper.map(value));
}
/**
@@ -153,7 +154,7 @@ public final class InternalJSONUtil {
* 为了能在HTML中较好的显示,会将</转义为<\/
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
- * @param str 字符串
+ * @param str 字符串
* @param appendable {@link Appendable}
* @throws IORuntimeException IO异常
*/
@@ -166,9 +167,9 @@ public final class InternalJSONUtil {
* 为了能在HTML中较好的显示,会将</转义为<\/
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
- * @param str 字符串
+ * @param str 字符串
* @param appendable {@link Appendable}
- * @param isWrap 是否使用双引号包装字符串
+ * @param isWrap 是否使用双引号包装字符串
* @return Writer
* @throws IORuntimeException IO异常
* @since 3.3.1
@@ -206,13 +207,16 @@ public final class InternalJSONUtil {
* 根据配置创建对应的原始Map
*
* @param capacity 初始大小
- * @param config JSON配置项,{@code null}则使用默认配置
+ * @param factory JSON工厂,{@code null}则使用默认配置
* @return Map
*/
- static Map createRawMap(final int capacity, final JSONConfig config) {
- final Map rawHashMap;
+ static Map createRawMap(final int capacity, final JSONFactory factory) {
+ final JSONConfig config = ObjUtil.apply(factory, JSONFactory::getConfig);
+ final boolean ignoreCase = ObjUtil.defaultIfNull(config, JSONConfig::isIgnoreCase, false);
final Comparator keyComparator = ObjUtil.apply(config, JSONConfig::getKeyComparator);
- if (null != config && config.isIgnoreCase()) {
+
+ final Map rawHashMap;
+ if (ignoreCase) {
if (null != keyComparator) {
rawHashMap = new CaseInsensitiveTreeMap<>(keyComparator);
} else {
@@ -295,10 +299,10 @@ public final class InternalJSONUtil {
return "\\r";
default:
if (c < CharUtil.SPACE || //
- (c >= '\u0080' && c <= '\u00a0') || //
- (c >= '\u2000' && c <= '\u2010') || //
- (c >= '\u2028' && c <= '\u202F') || //
- (c >= '\u2066' && c <= '\u206F')//
+ (c >= '\u0080' && c <= '\u00a0') || //
+ (c >= '\u2000' && c <= '\u2010') || //
+ (c >= '\u2028' && c <= '\u202F') || //
+ (c >= '\u2066' && c <= '\u206F')//
) {
return HexUtil.toUnicodeHex(c);
} else {
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/JSON.java b/hutool-json/src/main/java/org/dromara/hutool/json/JSON.java
index b931e3232..78f9d1646 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/JSON.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/JSON.java
@@ -18,8 +18,6 @@ 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.json.serializer.JSONMapper;
-import org.dromara.hutool.json.support.JSONNodeBeanFactory;
import org.dromara.hutool.json.writer.JSONWriter;
import java.io.Serializable;
@@ -147,7 +145,7 @@ public interface JSON extends Serializable {
return null;
}
- return JSONMapper.of(config(), null).toBean(json, resultType);
+ return json.toBean(resultType);
}
/**
@@ -171,7 +169,7 @@ public interface JSON extends Serializable {
* @see BeanPath#getValue(Object)
*/
default JSON getByPath(final String expression) {
- return (JSON) BeanPath.of(expression).getValue(this);
+ return (JSON) JSONFactory.of(config(), null).ofBeanPath(expression).getValue(this);
}
/**
@@ -196,7 +194,7 @@ public interface JSON extends Serializable {
* @param value 值
*/
default void putByPath(final String expression, final Object value) {
- BeanPath.of(expression, new JSONNodeBeanFactory(config())).setValue(this, value);
+ JSONFactory.of(config(), null).ofBeanPath(expression).setValue(this, value);
}
/**
@@ -214,25 +212,25 @@ public interface JSON extends Serializable {
* 格式化输出JSON字符串
*
* @param indentFactor 每层缩进空格数
- * @param predicate 过滤器,用于过滤不需要的键值对
* @return JSON字符串
* @throws JSONException 包含非法数抛出此异常
*/
- default String toJSONString(final int indentFactor, final Predicate> predicate) throws JSONException {
- final JSONWriter jsonWriter = JSONWriter.of(new StringBuilder(), indentFactor, 0, config()).setPredicate(predicate);
- this.write(jsonWriter);
- return jsonWriter.toString();
+ default String toJSONString(final int indentFactor) throws JSONException {
+ return toJSONString(indentFactor, null);
}
/**
* 格式化输出JSON字符串
*
* @param indentFactor 每层缩进空格数
+ * @param predicate 过滤器,用于过滤不需要的键值对
* @return JSON字符串
* @throws JSONException 包含非法数抛出此异常
*/
- default String toJSONString(final int indentFactor) throws JSONException {
- return toJSONString(indentFactor, null);
+ default String toJSONString(final int indentFactor, final Predicate> predicate) throws JSONException {
+ final JSONWriter jsonWriter = JSONFactory.of(config(), predicate).ofWriter(new StringBuilder(), indentFactor);
+ this.write(jsonWriter);
+ return jsonWriter.toString();
}
/**
@@ -252,6 +250,6 @@ public interface JSON extends Serializable {
* @return 实体类对象
*/
default T toBean(final Type type) {
- return JSONMapper.of(config(), null).toBean(this, type);
+ return JSONFactory.of(config(), null).toBean(this, type);
}
}
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/JSONArray.java b/hutool-json/src/main/java/org/dromara/hutool/json/JSONArray.java
index 6c76b4341..4f937b5ed 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/JSONArray.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/JSONArray.java
@@ -20,8 +20,6 @@ import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.collection.ListWrapper;
import org.dromara.hutool.core.lang.Validator;
import org.dromara.hutool.core.lang.mutable.MutableEntry;
-import org.dromara.hutool.core.util.ObjUtil;
-import org.dromara.hutool.json.serializer.JSONMapper;
import org.dromara.hutool.json.serializer.impl.ArrayTypeAdapter;
import org.dromara.hutool.json.serializer.impl.IterTypeAdapter;
import org.dromara.hutool.json.writer.JSONWriter;
@@ -47,11 +45,7 @@ public class JSONArray extends ListWrapper implements JSON, JSONGetter implements JSON, JSONGetter implements JSON, JSONGetter
+ * 默认使用{@link ArrayList} 实现
+ *
+ * @param initialCapacity 初始大小
+ * @param factory JSON工厂
+ */
+ public JSONArray(final int initialCapacity, final JSONFactory factory) {
super(new ArrayList<>(initialCapacity));
- this.config = ObjUtil.defaultIfNull(config, JSONConfig::of);
- this.mapper = JSONMapper.of(config, null);
+ this.factory = factory;
}
// endregion
@Override
public JSONConfig config() {
- return this.config;
+ return factory.getConfig();
}
@Override
@@ -119,7 +121,7 @@ public class JSONArray extends ListWrapper implements JSON, JSONGetter implements JSON, JSONGetter implements JSON, JSONGetter list = new ArrayList<>(c.size());
for (final JSON json : c) {
- if (null == json && config.isIgnoreNullValue()) {
+ if (null == json && config().isIgnoreNullValue()) {
continue;
}
list.add(json);
@@ -170,7 +172,7 @@ public class JSONArray extends ListWrapper implements JSON, JSONGetter implements JSON, JSONGetter implements JSON, JSONGetter implements JSON, JSONGetter
+ * entry中,key在JSONObject中为name,在JSONArray中为index
+ */
private final Predicate> predicate;
- private final JSONMapper mapper;
+ private volatile JSONMapper mapper;
/**
* 构造
@@ -56,16 +81,41 @@ public class JSONFactory {
public JSONFactory(final JSONConfig config, final Predicate> predicate) {
this.config = ObjUtil.defaultIfNull(config, JSONConfig::of);
this.predicate = predicate;
- this.mapper = JSONMapper.of(config, predicate);
}
/**
- * 获取{@link JSONMapper}
+ * 获取配置项
+ *
+ * @return 配置项
+ */
+ public JSONConfig getConfig() {
+ return this.config;
+ }
+
+ /**
+ * 获取键值对过滤器
+ *
+ * @return 键值对过滤器
+ */
+ public Predicate> getPredicate() {
+ return this.predicate;
+ }
+
+ /**
+ * 获取{@link JSONMapper},用于实现Bean和JSON的转换
+ * 此方法使用双重检查锁实现懒加载模式,只有mapper被使用时才初始化
*
* @return {@link JSONMapper}
*/
public JSONMapper getMapper() {
- return mapper;
+ if (null == this.mapper) {
+ synchronized (this) {
+ if (null == this.mapper) {
+ this.mapper = JSONMapper.of(this);
+ }
+ }
+ }
+ return this.mapper;
}
// region ----- of
@@ -76,7 +126,7 @@ public class JSONFactory {
* @return JSONObject
*/
public JSONObject ofObj() {
- return new JSONObject(this.config);
+ return new JSONObject(JSONObject.DEFAULT_CAPACITY, this);
}
/**
@@ -85,7 +135,7 @@ public class JSONFactory {
* @return JSONArray
*/
public JSONArray ofArray() {
- return new JSONArray(this.config);
+ return new JSONArray(JSONArray.DEFAULT_CAPACITY, this);
}
/**
@@ -95,7 +145,59 @@ public class JSONFactory {
* @return JSONPrimitive
*/
public JSONPrimitive ofPrimitive(final Object value) {
- return new JSONPrimitive(value, this.config);
+ return new JSONPrimitive(value, this);
+ }
+
+ /**
+ * 创建{@link JSONParser},用于JSON解析
+ *
+ * @param tokener {@link JSONTokener}
+ * @return {@link JSONParser}
+ */
+ public JSONParser ofParser(final JSONTokener tokener){
+ return JSONParser.of(tokener, this.config).setPredicate(this.predicate);
+ }
+
+ /**
+ * 创建{@link JSONWriter},用于JSON写出
+ *
+ * @param appendable {@link Appendable}
+ * @return {@link JSONWriter}
+ */
+ public JSONWriter ofWriter(final Appendable appendable) {
+ return ofWriter(appendable, 0);
+ }
+
+ /**
+ * 创建{@link JSONWriter},用于JSON写出
+ *
+ * @param appendable {@link Appendable}
+ * @param prettyPrint 是否格式化输出
+ * @return {@link JSONWriter}
+ */
+ public JSONWriter ofWriter(final Appendable appendable, final boolean prettyPrint) {
+ return ofWriter(appendable, prettyPrint ? 2 : 0);
+ }
+
+ /**
+ * 创建{@link JSONWriter},用于JSON写出
+ *
+ * @param appendable {@link Appendable}
+ * @param indentFactor 缩进因子,定义每一级别增加的缩进量,用于格式化输出
+ * @return {@link JSONWriter}
+ */
+ public JSONWriter ofWriter(final Appendable appendable, final int indentFactor) {
+ return JSONWriter.of(appendable, indentFactor, config, predicate);
+ }
+
+ /**
+ * 创建BeanPath,用于使用路径方式访问或设置值
+ *
+ * @param expression BeanPath表达式
+ * @return BeanPath
+ */
+ public BeanPath ofBeanPath(final String expression) {
+ return BeanPath.of(expression, new JSONNodeBeanFactory(config));
}
// endregion
@@ -112,11 +214,11 @@ public class JSONFactory {
obj = new ByteArrayInputStream((byte[]) obj);
}
- final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
+ final JSONMapper mapper = getMapper();
if (obj instanceof CharSequence) {
- return (JSONObject) jsonMapper.map((CharSequence) obj);
+ return (JSONObject) mapper.map((CharSequence) obj);
}
- return jsonMapper.mapObj(obj);
+ return mapper.mapObj(obj);
}
/**
@@ -127,20 +229,19 @@ public class JSONFactory {
* 其它支持和自定义的对象(如集合、数组等)
*
*
- * @param obj 数组或集合对象
+ * @param obj 数组或集合对象
* @return JSONArray
*/
public JSONArray parseArray(final Object obj) {
+ final JSONMapper mapper = getMapper();
if (obj instanceof JSONObject) {
- final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
- return jsonMapper.mapFromJSONObject((JSONObject) obj);
+ return mapper.mapFromJSONObject((JSONObject) obj);
}
- final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
if (obj instanceof CharSequence) {
- return (JSONArray) jsonMapper.map((CharSequence) obj);
+ return (JSONArray) mapper.map((CharSequence) obj);
}
- return jsonMapper.mapArray(obj);
+ return mapper.mapArray(obj);
}
/**
@@ -156,6 +257,7 @@ public class JSONFactory {
* @return JSON(JSONObject or JSONArray)
*/
public JSON parse(final Object obj) {
+ final JSONMapper mapper = this.getMapper();
if (obj instanceof CharSequence) {
return mapper.map((CharSequence) obj);
}
@@ -174,7 +276,7 @@ public class JSONFactory {
* @return Bean对象
*/
public T toBean(final JSON json, final Type type) {
- return mapper.toBean(json, type);
+ return getMapper().toBean(json, type);
}
// endregion
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/JSONObject.java b/hutool-json/src/main/java/org/dromara/hutool/json/JSONObject.java
index 1161583a1..b3d7b5725 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/JSONObject.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/JSONObject.java
@@ -25,7 +25,6 @@ import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.map.MapWrapper;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
-import org.dromara.hutool.json.serializer.JSONMapper;
import org.dromara.hutool.json.writer.JSONWriter;
import java.util.Arrays;
@@ -49,17 +48,23 @@ public class JSONObject extends MapWrapper implements JSON, JSONGe
*/
public static final int DEFAULT_CAPACITY = MapUtil.DEFAULT_INITIAL_CAPACITY;
- /**
- * 配置项
- */
- private final JSONConfig config;
- private final JSONMapper mapper;
+ private final JSONFactory factory;
+ // region ----- 构造
/**
* 构造,初始容量为 {@link #DEFAULT_CAPACITY},KEY有序
*/
public JSONObject() {
- this(JSONConfig.of());
+ this(DEFAULT_CAPACITY);
+ }
+
+ /**
+ * 构造
+ *
+ * @param capacity 初始大小
+ */
+ public JSONObject(final int capacity) {
+ this(capacity, JSONFactory.getInstance());
}
/**
@@ -79,14 +84,24 @@ public class JSONObject extends MapWrapper implements JSON, JSONGe
* @param config JSON配置项,{@code null}则使用默认配置
*/
public JSONObject(final int capacity, final JSONConfig config) {
- super(InternalJSONUtil.createRawMap(capacity, config));
- this.config = ObjUtil.defaultIfNull(config, JSONConfig::of);
- this.mapper = JSONMapper.of(config, null);
+ this(capacity, JSONFactory.of(config, null));
}
+ /**
+ * 构造
+ *
+ * @param capacity 初始大小
+ * @param factory JSON工厂类
+ */
+ public JSONObject(final int capacity, final JSONFactory factory) {
+ super(InternalJSONUtil.createRawMap(capacity, factory));
+ this.factory = factory;
+ }
+ // endregion
+
@Override
public JSONConfig config() {
- return this.config;
+ return this.factory.getConfig();
}
@Override
@@ -174,7 +189,7 @@ public class JSONObject extends MapWrapper implements JSON, JSONGe
} else if (object instanceof JSONArray) {
((JSONArray) object).set(value);
} else {
- this.set(key, JSONUtil.ofArray(this.config).set(object).set(value));
+ this.set(key, factory.ofArray().set(object).set(value));
}
return this;
}
@@ -220,7 +235,7 @@ public class JSONObject extends MapWrapper implements JSON, JSONGe
* @throws JSONException 值是无穷数字抛出此异常
*/
public JSONObject set(final String key, final Object value) throws JSONException {
- this.put(key, this.mapper.map(value));
+ this.put(key, factory.getMapper().map(value));
return this;
}
@@ -238,11 +253,11 @@ public class JSONObject extends MapWrapper implements JSON, JSONGe
return null;
}
- final boolean ignoreNullValue = this.config.isIgnoreNullValue();
+ final boolean ignoreNullValue = config().isIgnoreNullValue();
if (null == value && ignoreNullValue) {
// 忽略值模式下如果值为空清除key
return this.remove(key);
- } else if (this.config.isCheckDuplicate() && containsKey(key)) {
+ } else if (config().isCheckDuplicate() && containsKey(key)) {
throw new JSONException("Duplicate key \"{}\"", key);
}
return super.put(key, value);
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/JSONPrimitive.java b/hutool-json/src/main/java/org/dromara/hutool/json/JSONPrimitive.java
index 24c1e3296..d16775503 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/JSONPrimitive.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/JSONPrimitive.java
@@ -70,11 +70,8 @@ public class JSONPrimitive implements Wrapper