remove JSONStringer

This commit is contained in:
Looly
2024-09-14 01:10:51 +08:00
parent ee13716d42
commit 70b4f773e4
86 changed files with 959 additions and 939 deletions

View File

@@ -28,8 +28,8 @@ import org.dromara.hutool.core.math.NumberUtil;
import org.dromara.hutool.core.text.CharUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.text.split.SplitUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.reader.JSONTokener;
import org.dromara.hutool.json.serializer.JSONStringer;
import java.io.IOException;
import java.io.StringWriter;
@@ -94,10 +94,8 @@ public final class InternalJSONUtil {
/**
* 值转为String用于JSON中。规则为
* <ul>
* <li>对象如果实现了{@link JSONStringer}接口,调用{@link JSONStringer#toJSONString()}方法</li>
* <li>对象如果实现了{@link JSONStringer}接口,调用{@link JSONStringer#toJSONString()}方法</li>
* <li>对象如果是数组或Collection包装为{@link JSONArray}</li>
* <li>对象如果是Map包装为{@link JSONObject}</li>
* <li>对象如果是Map包装为{@link OldJSONObject}</li>
* <li>对象如果是数字,使用{@link NumberUtil#toStr(Number)}转换为字符串</li>
* <li>其他情况调用toString并使用双引号包装</li>
* </ul>
@@ -110,19 +108,13 @@ public final class InternalJSONUtil {
if (value == null) {
return StrUtil.NULL;
}
if (value instanceof JSONStringer) {
try {
return ((JSONStringer) value).toJSONString();
} catch (final Exception e) {
throw new JSONException(e);
}
} else if (value instanceof Number) {
if (value instanceof Number) {
return NumberUtil.toStr((Number) value);
} else if (value instanceof Boolean || value instanceof JSONObject || value instanceof JSONArray) {
} else if (value instanceof Boolean || value instanceof OldJSONObject || value instanceof JSONArray) {
return value.toString();
} else if (value instanceof Map) {
final Map<?, ?> map = (Map<?, ?>) value;
return new JSONObject(map).toString();
return new OldJSONObject(map).toString();
} else if (value instanceof Collection) {
final Collection<?> coll = (Collection<?>) value;
return new JSONArray(coll).toString();
@@ -143,15 +135,15 @@ public final class InternalJSONUtil {
* @param value 值
* @param predicate 属性过滤器,{@link Predicate#test(Object)}为{@code true}保留
*/
public static void propertyPut(final JSONObject jsonObject, final Object key, final Object value, final Predicate<MutableEntry<Object, Object>> predicate) {
public static void propertyPut(final OldJSONObject jsonObject, final Object key, final Object value, final Predicate<MutableEntry<Object, Object>> predicate) {
final String[] path = SplitUtil.splitToArray(ConvertUtil.toStr(key), StrUtil.DOT);
final int last = path.length - 1;
JSONObject target = jsonObject;
OldJSONObject target = jsonObject;
for (int i = 0; i < last; i += 1) {
final String segment = path[i];
JSONObject nextTarget = target.getJSONObject(segment);
OldJSONObject nextTarget = target.getJSONObject(segment);
if (nextTarget == null) {
nextTarget = new JSONObject(target.config());
nextTarget = new OldJSONObject(target.config());
target.set(segment, nextTarget, predicate);
}
target = nextTarget;
@@ -282,7 +274,8 @@ public final class InternalJSONUtil {
* @param config JSON配置项{@code null}则使用默认配置
* @return Map
*/
static Map<String, Object> createRawMap(final int capacity, JSONConfig config) {
@Deprecated
static Map<String, Object> createRawMapOld(final int capacity, JSONConfig config) {
final Map<String, Object> rawHashMap;
if (null == config) {
config = JSONConfig.of();
@@ -304,6 +297,32 @@ public final class InternalJSONUtil {
return rawHashMap;
}
/**
* 根据配置创建对应的原始Map
*
* @param capacity 初始大小
* @param config JSON配置项{@code null}则使用默认配置
* @return Map
*/
static Map<String, JSON> createRawMap(final int capacity, final JSONConfig config) {
final Map<String, JSON> rawHashMap;
final Comparator<String> keyComparator = ObjUtil.apply(config, JSONConfig::getKeyComparator);
if (null != config && config.isIgnoreCase()) {
if (null != keyComparator) {
rawHashMap = new CaseInsensitiveTreeMap<>(keyComparator);
} else {
rawHashMap = new CaseInsensitiveLinkedMap<>(capacity);
}
} else {
if (null != keyComparator) {
rawHashMap = new TreeMap<>(keyComparator);
} else {
rawHashMap = new LinkedHashMap<>(capacity);
}
}
return rawHashMap;
}
// --------------------------------------------------------------------------------------------- Private method start
/**

View File

@@ -31,7 +31,7 @@ import java.util.function.Predicate;
/**
* JSON树模型接口表示树中的一个节点。实现包括
* <ul>
* <li>{@link JSONObject}表示键值对形式的节点</li>
* <li>{@link OldJSONObject}表示键值对形式的节点</li>
* <li>{@link JSONArray}表示列表形式的节点</li>
* <li>{@link JSONPrimitive}表示数字、Boolean、字符串形式的节点</li>
* <li>{@code null}表示空节点</li>

View File

@@ -259,11 +259,11 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
* @return A JSONObject无名或值返回null
* @throws JSONException 如果任何一个名为null
*/
public JSONObject toJSONObject(final JSONArray names) throws JSONException {
public OldJSONObject toJSONObject(final JSONArray names) throws JSONException {
if (names == null || names.size() == 0 || this.size() == 0) {
return null;
}
final JSONObject jo = new JSONObject(this.config);
final OldJSONObject jo = new OldJSONObject(this.config);
for (int i = 0; i < names.size(); i += 1) {
jo.set(names.getStr(i), this.getObj(i));
}

View File

@@ -92,21 +92,21 @@ public interface JSONGetter<K> extends TypeGetter<K> {
/**
* 获得JSONObject对象<br>
* 如果值为其它类型对象,尝试转换为{@link JSONObject}返回,否则抛出异常
* 如果值为其它类型对象,尝试转换为{@link OldJSONObject}返回,否则抛出异常
*
* @param key KEY
* @return JSONObject对象如果值为{@code null},返回{@code null}非JSONObject类型尝试转换转换失败抛出异常
*/
default JSONObject getJSONObject(final K key) {
default OldJSONObject getJSONObject(final K key) {
final Object object = this.getObj(key);
if (ObjUtil.isNull(object)) {
return null;
}
if (object instanceof JSON) {
return (JSONObject) object;
return (OldJSONObject) object;
}
return new JSONObject(object, config());
return new OldJSONObject(object, config());
}
/**
@@ -120,7 +120,7 @@ public interface JSONGetter<K> extends TypeGetter<K> {
* @since 3.1.1
*/
default <T> T getBean(final K key, final Class<T> beanType) {
final JSONObject obj = getJSONObject(key);
final OldJSONObject obj = getJSONObject(key);
return (null == obj) ? null : obj.toBean(beanType);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
* 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.
@@ -16,40 +16,16 @@
package org.dromara.hutool.json;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.func.LambdaInfo;
import org.dromara.hutool.core.func.LambdaUtil;
import org.dromara.hutool.core.func.SerFunction;
import org.dromara.hutool.core.func.SerSupplier;
import org.dromara.hutool.core.lang.mutable.MutableEntry;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.map.MapWrapper;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.mapper.JSONObjectMapper;
import org.dromara.hutool.json.mapper.JSONValueMapper;
import org.dromara.hutool.json.writer.JSONWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.function.Predicate;
/**
* JSON对象<br>
* 例:<br>
*
* <pre>
* json = new JSONObject().put(&quot;JSON&quot;, &quot;Hello, World!&quot;).toString();
* </pre>
*
* @author looly
*/
public class JSONObject extends MapWrapper<String, Object> implements JSON, JSONGetter<String> {
private static final long serialVersionUID = -330220388580734346L;
public class JSONObject extends MapWrapper<String, JSON> implements JSON{
/**
* 默认初始大小
@@ -60,12 +36,6 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
* 配置项
*/
private JSONConfig config;
/**
* 对象转换和包装用于将Java对象和值转换为JSON值
*/
private JSONValueMapper valueMapper;
// -------------------------------------------------------------------------------------------------------------------- Constructor start
/**
* 构造,初始容量为 {@link #DEFAULT_CAPACITY}KEY有序
@@ -89,371 +59,17 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
*
* @param capacity 初始大小
* @param config JSON配置项{@code null}则使用默认配置
* @since 4.1.19
*/
public JSONObject(final int capacity, final JSONConfig config) {
super(InternalJSONUtil.createRawMap(capacity, ObjUtil.defaultIfNull(config, JSONConfig.of())));
this.config = ObjUtil.defaultIfNull(config, JSONConfig.of());
this.valueMapper = JSONValueMapper.of(this.config);
super(InternalJSONUtil.createRawMap(capacity, config));
this.config = ObjUtil.defaultIfNull(config, JSONConfig::of);
}
/**
* 构建JSONObjectJavaBean默认忽略null值其它对象不忽略规则如下
* <ol>
* <li>value为Map将键值对加入JSON对象</li>
* <li>value为JSON字符串CharSequence使用JSONTokener解析</li>
* <li>value为JSONTokener直接解析</li>
* <li>value为普通JavaBean如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象。
* 例如如果JavaBean对象中有个方法getName(),值为"张三"获得的键值对为name: "张三"</li>
* </ol>
*
* @param source JavaBean或者Map对象或者String
*/
public JSONObject(final Object source) {
this(source, JSONConfig.of().setIgnoreNullValue(InternalJSONUtil.defaultIgnoreNullValue(source)));
}
/**
* 构建JSONObject规则如下
* <ol>
* <li>value为Map将键值对加入JSON对象</li>
* <li>value为JSON字符串CharSequence使用JSONTokener解析</li>
* <li>value为JSONTokener直接解析</li>
* <li>value为普通JavaBean如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象。例如如果JavaBean对象中有个方法getName(),值为"张三"获得的键值对为name: "张三"</li>
* </ol>
* <p>
* 如果给定值为Map将键值对加入JSON对象;<br>
* 如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象<br>
* 例如如果JavaBean对象中有个方法getName(),值为"张三"获得的键值对为name: "张三"
*
* @param source JavaBean或者Map对象或者String
* @param config JSON配置文件{@code null}则使用默认配置
* @since 4.2.2
*/
public JSONObject(final Object source, final JSONConfig config) {
this(source, config, null);
}
/**
* 构建JSONObject规则如下
* <ol>
* <li>value为Map将键值对加入JSON对象</li>
* <li>value为JSON字符串CharSequence使用JSONTokener解析</li>
* <li>value为JSONTokener直接解析</li>
* <li>value为普通JavaBean如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象。例如如果JavaBean对象中有个方法getName(),值为"张三"获得的键值对为name: "张三"</li>
* </ol>
* <p>
* 如果给定值为Map将键值对加入JSON对象;<br>
* 如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象<br>
* 例如如果JavaBean对象中有个方法getName(),值为"张三"获得的键值对为name: "张三"
*
* @param source JavaBean或者Map对象或者String
* @param config JSON配置文件{@code null}则使用默认配置
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留
* @since 5.8.0
*/
public JSONObject(final Object source, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
this(DEFAULT_CAPACITY, config);
JSONObjectMapper.of(source, predicate).mapTo(this);
}
// -------------------------------------------------------------------------------------------------------------------- Constructor end
@Override
public JSONConfig config() {
return this.config;
}
/**
* 设置转为字符串时的日期格式默认为时间戳null值<br>
* 此方法设置的日期格式仅对转换为JSON字符串有效对解析JSON为bean无效。
*
* @param format 格式null表示使用时间戳
* @return this
* @since 4.1.19
*/
public JSONObject setDateFormat(final String format) {
this.config.setDateFormat(format);
return this;
}
/**
* 将指定KEY列表的值组成新的JSONArray
*
* @param names KEY列表
* @return A JSONArray of values.
* @throws JSONException If any of the values are non-finite numbers.
*/
public JSONArray toJSONArray(final Collection<String> names) throws JSONException {
if (CollUtil.isEmpty(names)) {
return null;
}
final JSONArray ja = new JSONArray(this.config);
Object value;
for (final String name : names) {
value = this.get(name);
if (null != value) {
ja.set(value);
}
}
return ja;
}
@Override
public Object getObj(final String key, final Object defaultValue) {
return getOrDefault(key, defaultValue);
}
@Override
public Object get(final Object key) {
Object value = super.get(key);
if(value instanceof JSONPrimitive){
value = ((JSONPrimitive) value).getValue();
}
return value;
}
@Override
public Object getOrDefault(final Object key, final Object defaultValue) {
Object value = super.getOrDefault(key, defaultValue);
if(value instanceof JSONPrimitive){
value = ((JSONPrimitive) value).getValue();
}
return value;
}
/**
* 根据lambda的方法引用获取
*
* @param func 方法引用
* @param <P> 参数类型
* @param <T> 返回值类型
* @return 获取表达式对应属性和返回的对象
*/
public <P, T> T get(final SerFunction<P, T> func) {
final LambdaInfo lambdaInfo = LambdaUtil.resolve(func);
return get(lambdaInfo.getFieldName(), lambdaInfo.getReturnType());
}
/**
* PUT 键值对到JSONObject中在忽略null模式下如果值为{@code null},将此键移除
*
* @param key 键
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException 值是无穷数字抛出此异常
*/
@Override
public Object put(final String key, final Object value) throws JSONException {
return put(key, value, null, config().isCheckDuplicate());
}
/**
* 设置键值对到JSONObject中在忽略null模式下如果值为{@code null},将此键移除
*
* @param key 键
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException 值是无穷数字抛出此异常
*/
public JSONObject set(final String key, final Object value) throws JSONException {
set(key, value, null);
return this;
}
/**
* 通过lambda批量设置值<br>
* 实际使用时可以使用getXXX的方法引用来完成键值对的赋值
* <pre>
* User user = GenericBuilder.of(User::new).with(User::setUsername, "hutool").build();
* (new JSONObject()).setFields(user::getNickname, user::getUsername);
* </pre>
*
* @param fields lambda,不能为空
* @return this
*/
public JSONObject setFields(final SerSupplier<?>... fields) {
Arrays.stream(fields).forEach(f -> set(LambdaUtil.getFieldName(f), f.get()));
return this;
}
/**
* 一次性Put 键值对如果key已经存在抛出异常如果键值中有null值忽略
*
* @param key 键
* @param value 值对象,可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留
* @return this
* @throws JSONException 值是无穷数字、键重复抛出异常
* @since 5.8.0
*/
public JSONObject set(final String key, final Object value, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
put(key, value, predicate, config().isCheckDuplicate());
return this;
}
/**
* 设置键值对到JSONObject中在忽略null模式下如果值为{@code null},将此键移除
*
* @param key 键
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留
* @param checkDuplicate 是否检查重复键,如果为{@code true},则出现重复键时抛出{@link JSONException}异常
* @return this.
* @throws JSONException 值是无穷数字抛出此异常
* @since 5.8.0
*/
public JSONObject set(final String key, final Object value, final Predicate<MutableEntry<Object, Object>> predicate, final boolean checkDuplicate) throws JSONException {
put(key, value, predicate, checkDuplicate);
return this;
}
/**
* 在键和值都为非空的情况下put到JSONObject中
*
* @param key 键
* @param value 值对象,可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException 值是无穷数字
*/
public JSONObject setOpt(final String key, final Object value) throws JSONException {
if (key != null && value != null) {
this.set(key, value);
}
return this;
}
@Override
public void putAll(final Map<? extends String, ?> m) {
for (final Entry<? extends String, ?> entry : m.entrySet()) {
this.set(entry.getKey(), entry.getValue());
}
}
/**
* 追加值.
* <ul>
* <li>如果键值对不存在或对应值为{@code null}则value为单独值</li>
* <li>如果值是一个{@link JSONArray},追加之</li>
* <li>如果值是一个其他值,则和旧值共同组合为一个{@link JSONArray}</li>
* </ul>
*
* @param key 键
* @param value 值
* @return this.
* @throws JSONException 如果给定键为{@code null}或者键对应的值存在且为非JSONArray
*/
public JSONObject append(final String key, final Object value) throws JSONException {
return append(key, value, null);
}
/**
* 追加值.
* <ul>
* <li>如果键值对不存在或对应值为{@code null}则value为单独值</li>
* <li>如果值是一个{@link JSONArray},追加之</li>
* <li>如果值是一个其他值,则和旧值共同组合为一个{@link JSONArray}</li>
* </ul>
*
* @param key 键
* @param value 值
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留
* @return this.
* @throws JSONException 如果给定键为{@code null}或者键对应的值存在且为非JSONArray
* @since 6.0.0
*/
public JSONObject append(String key, Object value, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
// 添加前置过滤通过MutablePair实现过滤、修改键值对等
if (null != predicate) {
final MutableEntry<Object, Object> pair = new MutableEntry<>(key, value);
if (predicate.test(pair)) {
// 使用修改后的键值对
key = (String) pair.getKey();
value = pair.getValue();
} else {
// 键值对被过滤
return this;
}
}
final Object object = this.getObj(key);
if (object == null) {
this.set(key, value);
} else if (object instanceof JSONArray) {
((JSONArray) object).set(value);
} else {
this.set(key, JSONUtil.ofArray(this.config).set(object).set(value));
}
return this;
}
/**
* 对值加一如果值不存在赋值1如果为数字类型做加一操作
*
* @param key A key string.
* @return this.
* @throws JSONException 如果存在值非Integer, Long, Double, 或 Float.
*/
public JSONObject increment(final String key) throws JSONException {
final Object value = this.getObj(key);
if (value == null) {
this.set(key, 1);
} else if (value instanceof BigInteger) {
this.set(key, ((BigInteger) value).add(BigInteger.ONE));
} else if (value instanceof BigDecimal) {
this.set(key, ((BigDecimal) value).add(BigDecimal.ONE));
} else if (value instanceof Integer) {
this.set(key, (Integer) value + 1);
} else if (value instanceof Long) {
this.set(key, (Long) value + 1);
} else if (value instanceof Double) {
this.set(key, (Double) value + 1);
} else if (value instanceof Float) {
this.set(key, (Float) value + 1);
} else {
throw new JSONException("Unable to increment [" + InternalJSONUtil.quote(key) + "].");
}
return this;
}
/**
* 返回JSON字符串<br>
* 如果解析错误,返回{@code null}
*
* @return JSON字符串
*/
@Override
public String toString() {
return this.toJSONString(0);
}
/**
* 返回JSON字符串<br>
* 支持过滤器,即选择哪些字段或值不写出
*
* @param indentFactor 每层缩进空格数
* @param predicate 过滤器,同时可以修改编辑键和值,{@link Predicate#test(Object)}为{@code true}保留
* @return JSON字符串
* @since 5.7.15
*/
public String toJSONString(final int indentFactor, final Predicate<MutableEntry<Object, Object>> predicate) {
final StringWriter sw = new StringWriter();
synchronized (sw.getBuffer()) {
return this.write(sw, indentFactor, 0, predicate).toString();
}
}
/**
* 将JSON内容写入Writer<br>
* 支持过滤器,即选择哪些字段或值不写出
*
* @param writer writer
* @param indentFactor 缩进因子,定义每一级别增加的缩进量
* @param indent 本级别缩进量
* @param predicate 过滤器,同时可以修改编辑键和值
* @return Writer
* @throws JSONException JSON相关异常
* @since 5.7.15
*/
@Override
public Writer write(final Writer writer, final int indentFactor, final int indent, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config)
@@ -463,51 +79,4 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
// 此处不关闭Writer考虑writer后续还需要填内容
return writer;
}
@Override
public JSONObject clone() throws CloneNotSupportedException {
final JSONObject clone = (JSONObject) super.clone();
clone.config = this.config;
clone.valueMapper = this.valueMapper;
return clone;
}
/**
* 设置键值对到JSONObject中在忽略null模式下如果值为{@code null},将此键移除
*
* @param key 键
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留
* @param checkDuplicate 是否检查重复键,如果为{@code true},则出现重复键时抛出{@link JSONException}异常
* @return 旧值
* @throws JSONException 值是无穷数字抛出此异常
* @since 5.8.0
*/
private Object put(String key, Object value, final Predicate<MutableEntry<Object, Object>> predicate, final boolean checkDuplicate) throws JSONException {
if (null == key) {
return null;
}
// 添加前置过滤通过MutablePair实现过滤、修改键值对等
if (null != predicate) {
final MutableEntry<Object, Object> pair = new MutableEntry<>(key, value);
if (predicate.test(pair)) {
// 使用修改后的键值对
key = (String) pair.getKey();
value = pair.getValue();
} else {
// 键值对被过滤
return null;
}
}
final boolean ignoreNullValue = this.config.isIgnoreNullValue();
if (null == value && ignoreNullValue) {
// 忽略值模式下如果值为空清除key
return this.remove(key);
} else if (checkDuplicate && containsKey(key)) {
throw new JSONException("Duplicate key \"{}\"", key);
}
return super.put(key, this.valueMapper.map(value));
}
}

View File

@@ -18,9 +18,9 @@ package org.dromara.hutool.json;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.lang.mutable.MutableEntry;
import org.dromara.hutool.json.writer.GlobalValueWriters;
import org.dromara.hutool.json.writer.JSONValueWriter;
import org.dromara.hutool.json.writer.JSONWriter;
import org.dromara.hutool.json.writer.ValueWriter;
import org.dromara.hutool.json.writer.ValueWriterManager;
import java.io.StringWriter;
import java.io.Writer;
@@ -119,7 +119,7 @@ public class JSONPrimitive implements JSON {
final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config);
// 自定义规则
final JSONValueWriter valueWriter = GlobalValueWriters.get(value);
final ValueWriter valueWriter = ValueWriterManager.getInstance().get(value);
if (null != valueWriter) {
valueWriter.write(jsonWriter, value);
return writer;

View File

@@ -23,9 +23,9 @@ import org.dromara.hutool.core.reflect.TypeReference;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.convert.JSONConverter;
import org.dromara.hutool.json.writer.GlobalValueWriters;
import org.dromara.hutool.json.writer.JSONValueWriter;
import org.dromara.hutool.json.writer.JSONWriter;
import org.dromara.hutool.json.writer.ValueWriter;
import org.dromara.hutool.json.writer.ValueWriterManager;
import org.dromara.hutool.json.xml.JSONXMLUtil;
import java.io.File;
@@ -49,8 +49,8 @@ public class JSONUtil {
*
* @return JSONObject
*/
public static JSONObject ofObj() {
return new JSONObject();
public static OldJSONObject ofObj() {
return new OldJSONObject();
}
/**
@@ -60,8 +60,8 @@ public class JSONUtil {
* @return JSONObject
* @since 5.2.5
*/
public static JSONObject ofObj(final JSONConfig config) {
return new JSONObject(config);
public static OldJSONObject ofObj(final JSONConfig config) {
return new OldJSONObject(config);
}
/**
@@ -91,8 +91,8 @@ public class JSONUtil {
* @param obj Bean对象或者Map
* @return JSONObject
*/
public static JSONObject parseObj(final Object obj) {
return new JSONObject(obj);
public static OldJSONObject parseObj(final Object obj) {
return new OldJSONObject(obj);
}
/**
@@ -104,8 +104,8 @@ public class JSONUtil {
* @return JSONObject
* @since 5.3.1
*/
public static JSONObject parseObj(final Object obj, final JSONConfig config) {
return new JSONObject(obj, config);
public static OldJSONObject parseObj(final Object obj, final JSONConfig config) {
return new OldJSONObject(obj, config);
}
/**
@@ -116,8 +116,8 @@ public class JSONUtil {
* @return JSONObject
* @since 3.0.9
*/
public static JSONObject parseObj(final Object obj, final boolean ignoreNullValue) {
return new JSONObject(obj, JSONConfig.of().setIgnoreNullValue(ignoreNullValue));
public static OldJSONObject parseObj(final Object obj, final boolean ignoreNullValue) {
return new OldJSONObject(obj, JSONConfig.of().setIgnoreNullValue(ignoreNullValue));
}
/**
@@ -185,7 +185,7 @@ public class JSONUtil {
* @param xmlStr XML字符串
* @return JSONObject
*/
public static JSONObject parseFromXml(final String xmlStr) {
public static OldJSONObject parseFromXml(final String xmlStr) {
return JSONXMLUtil.toJSONObject(xmlStr);
}
// -------------------------------------------------------------------- Parse end
@@ -212,7 +212,7 @@ public class JSONUtil {
* @return JSONObject
* @throws IORuntimeException IO异常
*/
public static JSONObject readJSONObject(final File file, final Charset charset) throws IORuntimeException {
public static OldJSONObject readJSONObject(final File file, final Charset charset) throws IORuntimeException {
return FileUtil.read(file, charset, JSONUtil::parseObj);
}
@@ -261,7 +261,7 @@ public class JSONUtil {
*/
public static String toJsonStr(final Object obj, final JSONConfig jsonConfig) {
// 自定义规则,优先级高于全局规则
final JSONValueWriter valueWriter = GlobalValueWriters.get(obj);
final ValueWriter valueWriter = ValueWriterManager.getInstance().get(obj);
if (null != valueWriter) {
final StringWriter stringWriter = new StringWriter();
final JSONWriter jsonWriter = JSONWriter.of(stringWriter, 0, 0, null);
@@ -307,7 +307,7 @@ public class JSONUtil {
* @return JSONObject
* @since 4.0.8
*/
public static JSONObject xmlToJson(final String xml) {
public static OldJSONObject xmlToJson(final String xml) {
return JSONXMLUtil.toJSONObject(xml);
}
// -------------------------------------------------------------------- toString end
@@ -480,7 +480,7 @@ public class JSONUtil {
* <ul>
* <li>null</li>
* <li>{@link JSONArray#isEmpty()}</li>
* <li>{@link JSONObject#isEmpty()}</li>
* <li>{@link OldJSONObject#isEmpty()}</li>
* </ul>
*
* @param json JSONObject或JSONArray
@@ -490,8 +490,8 @@ public class JSONUtil {
if (null == json) {
return true;
}
if (json instanceof JSONObject) {
return ((JSONObject) json).isEmpty();
if (json instanceof OldJSONObject) {
return ((OldJSONObject) json).isEmpty();
} else if (json instanceof JSONArray) {
return ((JSONArray) json).isEmpty();
}

View File

@@ -0,0 +1,513 @@
/*
* 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;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.func.LambdaInfo;
import org.dromara.hutool.core.func.LambdaUtil;
import org.dromara.hutool.core.func.SerFunction;
import org.dromara.hutool.core.func.SerSupplier;
import org.dromara.hutool.core.lang.mutable.MutableEntry;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.map.MapWrapper;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.mapper.JSONObjectMapper;
import org.dromara.hutool.json.mapper.JSONValueMapper;
import org.dromara.hutool.json.writer.JSONWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.function.Predicate;
/**
* JSON对象<br>
* 例:<br>
*
* <pre>
* json = new JSONObject().put(&quot;JSON&quot;, &quot;Hello, World!&quot;).toString();
* </pre>
*
* @author looly
*/
public class OldJSONObject extends MapWrapper<String, Object> implements JSON, JSONGetter<String> {
private static final long serialVersionUID = -330220388580734346L;
/**
* 默认初始大小
*/
public static final int DEFAULT_CAPACITY = MapUtil.DEFAULT_INITIAL_CAPACITY;
/**
* 配置项
*/
private JSONConfig config;
/**
* 对象转换和包装用于将Java对象和值转换为JSON值
*/
private JSONValueMapper valueMapper;
// -------------------------------------------------------------------------------------------------------------------- Constructor start
/**
* 构造,初始容量为 {@link #DEFAULT_CAPACITY}KEY有序
*/
public OldJSONObject() {
this(JSONConfig.of());
}
/**
* 构造
*
* @param config JSON配置项
* @since 4.6.5
*/
public OldJSONObject(final JSONConfig config) {
this(DEFAULT_CAPACITY, config);
}
/**
* 构造
*
* @param capacity 初始大小
* @param config JSON配置项{@code null}则使用默认配置
* @since 4.1.19
*/
public OldJSONObject(final int capacity, final JSONConfig config) {
super(InternalJSONUtil.createRawMapOld(capacity, ObjUtil.defaultIfNull(config, JSONConfig.of())));
this.config = ObjUtil.defaultIfNull(config, JSONConfig.of());
this.valueMapper = JSONValueMapper.of(this.config);
}
/**
* 构建JSONObjectJavaBean默认忽略null值其它对象不忽略规则如下
* <ol>
* <li>value为Map将键值对加入JSON对象</li>
* <li>value为JSON字符串CharSequence使用JSONTokener解析</li>
* <li>value为JSONTokener直接解析</li>
* <li>value为普通JavaBean如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象。
* 例如如果JavaBean对象中有个方法getName(),值为"张三"获得的键值对为name: "张三"</li>
* </ol>
*
* @param source JavaBean或者Map对象或者String
*/
public OldJSONObject(final Object source) {
this(source, JSONConfig.of().setIgnoreNullValue(InternalJSONUtil.defaultIgnoreNullValue(source)));
}
/**
* 构建JSONObject规则如下
* <ol>
* <li>value为Map将键值对加入JSON对象</li>
* <li>value为JSON字符串CharSequence使用JSONTokener解析</li>
* <li>value为JSONTokener直接解析</li>
* <li>value为普通JavaBean如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象。例如如果JavaBean对象中有个方法getName(),值为"张三"获得的键值对为name: "张三"</li>
* </ol>
* <p>
* 如果给定值为Map将键值对加入JSON对象;<br>
* 如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象<br>
* 例如如果JavaBean对象中有个方法getName(),值为"张三"获得的键值对为name: "张三"
*
* @param source JavaBean或者Map对象或者String
* @param config JSON配置文件{@code null}则使用默认配置
* @since 4.2.2
*/
public OldJSONObject(final Object source, final JSONConfig config) {
this(source, config, null);
}
/**
* 构建JSONObject规则如下
* <ol>
* <li>value为Map将键值对加入JSON对象</li>
* <li>value为JSON字符串CharSequence使用JSONTokener解析</li>
* <li>value为JSONTokener直接解析</li>
* <li>value为普通JavaBean如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象。例如如果JavaBean对象中有个方法getName(),值为"张三"获得的键值对为name: "张三"</li>
* </ol>
* <p>
* 如果给定值为Map将键值对加入JSON对象;<br>
* 如果为普通的JavaBean调用其getters方法getXXX或者isXXX获得值加入到JSON对象<br>
* 例如如果JavaBean对象中有个方法getName(),值为"张三"获得的键值对为name: "张三"
*
* @param source JavaBean或者Map对象或者String
* @param config JSON配置文件{@code null}则使用默认配置
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留
* @since 5.8.0
*/
public OldJSONObject(final Object source, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
this(DEFAULT_CAPACITY, config);
JSONObjectMapper.of(source, predicate).mapTo(this);
}
// -------------------------------------------------------------------------------------------------------------------- Constructor end
@Override
public JSONConfig config() {
return this.config;
}
/**
* 设置转为字符串时的日期格式默认为时间戳null值<br>
* 此方法设置的日期格式仅对转换为JSON字符串有效对解析JSON为bean无效。
*
* @param format 格式null表示使用时间戳
* @return this
* @since 4.1.19
*/
public OldJSONObject setDateFormat(final String format) {
this.config.setDateFormat(format);
return this;
}
/**
* 将指定KEY列表的值组成新的JSONArray
*
* @param names KEY列表
* @return A JSONArray of values.
* @throws JSONException If any of the values are non-finite numbers.
*/
public JSONArray toJSONArray(final Collection<String> names) throws JSONException {
if (CollUtil.isEmpty(names)) {
return null;
}
final JSONArray ja = new JSONArray(this.config);
Object value;
for (final String name : names) {
value = this.get(name);
if (null != value) {
ja.set(value);
}
}
return ja;
}
@Override
public Object getObj(final String key, final Object defaultValue) {
return getOrDefault(key, defaultValue);
}
@Override
public Object get(final Object key) {
Object value = super.get(key);
if(value instanceof JSONPrimitive){
value = ((JSONPrimitive) value).getValue();
}
return value;
}
@Override
public Object getOrDefault(final Object key, final Object defaultValue) {
Object value = super.getOrDefault(key, defaultValue);
if(value instanceof JSONPrimitive){
value = ((JSONPrimitive) value).getValue();
}
return value;
}
/**
* 根据lambda的方法引用获取
*
* @param func 方法引用
* @param <P> 参数类型
* @param <T> 返回值类型
* @return 获取表达式对应属性和返回的对象
*/
public <P, T> T get(final SerFunction<P, T> func) {
final LambdaInfo lambdaInfo = LambdaUtil.resolve(func);
return get(lambdaInfo.getFieldName(), lambdaInfo.getReturnType());
}
/**
* PUT 键值对到JSONObject中在忽略null模式下如果值为{@code null},将此键移除
*
* @param key 键
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException 值是无穷数字抛出此异常
*/
@Override
public Object put(final String key, final Object value) throws JSONException {
return put(key, value, null, config().isCheckDuplicate());
}
/**
* 设置键值对到JSONObject中在忽略null模式下如果值为{@code null},将此键移除
*
* @param key 键
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException 值是无穷数字抛出此异常
*/
public OldJSONObject set(final String key, final Object value) throws JSONException {
set(key, value, null);
return this;
}
/**
* 通过lambda批量设置值<br>
* 实际使用时可以使用getXXX的方法引用来完成键值对的赋值
* <pre>
* User user = GenericBuilder.of(User::new).with(User::setUsername, "hutool").build();
* (new JSONObject()).setFields(user::getNickname, user::getUsername);
* </pre>
*
* @param fields lambda,不能为空
* @return this
*/
public OldJSONObject setFields(final SerSupplier<?>... fields) {
Arrays.stream(fields).forEach(f -> set(LambdaUtil.getFieldName(f), f.get()));
return this;
}
/**
* 一次性Put 键值对如果key已经存在抛出异常如果键值中有null值忽略
*
* @param key 键
* @param value 值对象,可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留
* @return this
* @throws JSONException 值是无穷数字、键重复抛出异常
* @since 5.8.0
*/
public OldJSONObject set(final String key, final Object value, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
put(key, value, predicate, config().isCheckDuplicate());
return this;
}
/**
* 设置键值对到JSONObject中在忽略null模式下如果值为{@code null},将此键移除
*
* @param key 键
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留
* @param checkDuplicate 是否检查重复键,如果为{@code true},则出现重复键时抛出{@link JSONException}异常
* @return this.
* @throws JSONException 值是无穷数字抛出此异常
* @since 5.8.0
*/
public OldJSONObject set(final String key, final Object value, final Predicate<MutableEntry<Object, Object>> predicate, final boolean checkDuplicate) throws JSONException {
put(key, value, predicate, checkDuplicate);
return this;
}
/**
* 在键和值都为非空的情况下put到JSONObject中
*
* @param key 键
* @param value 值对象,可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException 值是无穷数字
*/
public OldJSONObject setOpt(final String key, final Object value) throws JSONException {
if (key != null && value != null) {
this.set(key, value);
}
return this;
}
@Override
public void putAll(final Map<? extends String, ?> m) {
for (final Entry<? extends String, ?> entry : m.entrySet()) {
this.set(entry.getKey(), entry.getValue());
}
}
/**
* 追加值.
* <ul>
* <li>如果键值对不存在或对应值为{@code null}则value为单独值</li>
* <li>如果值是一个{@link JSONArray},追加之</li>
* <li>如果值是一个其他值,则和旧值共同组合为一个{@link JSONArray}</li>
* </ul>
*
* @param key 键
* @param value 值
* @return this.
* @throws JSONException 如果给定键为{@code null}或者键对应的值存在且为非JSONArray
*/
public OldJSONObject append(final String key, final Object value) throws JSONException {
return append(key, value, null);
}
/**
* 追加值.
* <ul>
* <li>如果键值对不存在或对应值为{@code null}则value为单独值</li>
* <li>如果值是一个{@link JSONArray},追加之</li>
* <li>如果值是一个其他值,则和旧值共同组合为一个{@link JSONArray}</li>
* </ul>
*
* @param key 键
* @param value 值
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留
* @return this.
* @throws JSONException 如果给定键为{@code null}或者键对应的值存在且为非JSONArray
* @since 6.0.0
*/
public OldJSONObject append(String key, Object value, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
// 添加前置过滤通过MutablePair实现过滤、修改键值对等
if (null != predicate) {
final MutableEntry<Object, Object> pair = new MutableEntry<>(key, value);
if (predicate.test(pair)) {
// 使用修改后的键值对
key = (String) pair.getKey();
value = pair.getValue();
} else {
// 键值对被过滤
return this;
}
}
final Object object = this.getObj(key);
if (object == null) {
this.set(key, value);
} else if (object instanceof JSONArray) {
((JSONArray) object).set(value);
} else {
this.set(key, JSONUtil.ofArray(this.config).set(object).set(value));
}
return this;
}
/**
* 对值加一如果值不存在赋值1如果为数字类型做加一操作
*
* @param key A key string.
* @return this.
* @throws JSONException 如果存在值非Integer, Long, Double, 或 Float.
*/
public OldJSONObject increment(final String key) throws JSONException {
final Object value = this.getObj(key);
if (value == null) {
this.set(key, 1);
} else if (value instanceof BigInteger) {
this.set(key, ((BigInteger) value).add(BigInteger.ONE));
} else if (value instanceof BigDecimal) {
this.set(key, ((BigDecimal) value).add(BigDecimal.ONE));
} else if (value instanceof Integer) {
this.set(key, (Integer) value + 1);
} else if (value instanceof Long) {
this.set(key, (Long) value + 1);
} else if (value instanceof Double) {
this.set(key, (Double) value + 1);
} else if (value instanceof Float) {
this.set(key, (Float) value + 1);
} else {
throw new JSONException("Unable to increment [" + InternalJSONUtil.quote(key) + "].");
}
return this;
}
/**
* 返回JSON字符串<br>
* 如果解析错误,返回{@code null}
*
* @return JSON字符串
*/
@Override
public String toString() {
return this.toJSONString(0);
}
/**
* 返回JSON字符串<br>
* 支持过滤器,即选择哪些字段或值不写出
*
* @param indentFactor 每层缩进空格数
* @param predicate 过滤器,同时可以修改编辑键和值,{@link Predicate#test(Object)}为{@code true}保留
* @return JSON字符串
* @since 5.7.15
*/
public String toJSONString(final int indentFactor, final Predicate<MutableEntry<Object, Object>> predicate) {
final StringWriter sw = new StringWriter();
synchronized (sw.getBuffer()) {
return this.write(sw, indentFactor, 0, predicate).toString();
}
}
/**
* 将JSON内容写入Writer<br>
* 支持过滤器,即选择哪些字段或值不写出
*
* @param writer writer
* @param indentFactor 缩进因子,定义每一级别增加的缩进量
* @param indent 本级别缩进量
* @param predicate 过滤器,同时可以修改编辑键和值
* @return Writer
* @throws JSONException JSON相关异常
* @since 5.7.15
*/
@Override
public Writer write(final Writer writer, final int indentFactor, final int indent, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config)
.beginObj();
this.forEach((key, value) -> jsonWriter.writeField(new MutableEntry<>(key, value), predicate));
jsonWriter.end();
// 此处不关闭Writer考虑writer后续还需要填内容
return writer;
}
@Override
public OldJSONObject clone() throws CloneNotSupportedException {
final OldJSONObject clone = (OldJSONObject) super.clone();
clone.config = this.config;
clone.valueMapper = this.valueMapper;
return clone;
}
/**
* 设置键值对到JSONObject中在忽略null模式下如果值为{@code null},将此键移除
*
* @param key 键
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留
* @param checkDuplicate 是否检查重复键,如果为{@code true},则出现重复键时抛出{@link JSONException}异常
* @return 旧值
* @throws JSONException 值是无穷数字抛出此异常
* @since 5.8.0
*/
private Object put(String key, Object value, final Predicate<MutableEntry<Object, Object>> predicate, final boolean checkDuplicate) throws JSONException {
if (null == key) {
return null;
}
// 添加前置过滤通过MutablePair实现过滤、修改键值对等
if (null != predicate) {
final MutableEntry<Object, Object> pair = new MutableEntry<>(key, value);
if (predicate.test(pair)) {
// 使用修改后的键值对
key = (String) pair.getKey();
value = pair.getValue();
} else {
// 键值对被过滤
return null;
}
}
final boolean ignoreNullValue = this.config.isIgnoreNullValue();
if (null == value && ignoreNullValue) {
// 忽略值模式下如果值为空清除key
return this.remove(key);
} else if (checkDuplicate && containsKey(key)) {
throw new JSONException("Duplicate key \"{}\"", key);
}
return super.put(key, this.valueMapper.map(value));
}
}

View File

@@ -69,7 +69,7 @@ public class JSONConverter implements Converter, Serializable {
public static JSONConverter of(final JSONConfig config) {
final JSONConverter jsonConverter = new JSONConverter(config);
jsonConverter.registerConverter = new RegisterConverter(jsonConverter)
.register(JSONObject.class, INSTANCE)
.register(OldJSONObject.class, INSTANCE)
.register(JSONArray.class, INSTANCE)
.register(JSONPrimitive.class, INSTANCE);
jsonConverter.specialConverter = new SpecialConverter(jsonConverter);
@@ -94,10 +94,6 @@ public class JSONConverter implements Converter, Serializable {
if (null == value) {
return null;
}
if (value instanceof JSONStringer) {
// 被JSONString包装的对象获取其原始类型
value = ((JSONStringer) value).getRaw();
}
// JSON转对象
if (value instanceof JSON) {
@@ -173,11 +169,11 @@ public class JSONConverter implements Converter, Serializable {
return toJSON((CharSequence) obj);
} else if (obj instanceof MapWrapper) {
// MapWrapper实现了Iterable会被当作JSONArray此处做修正
json = new JSONObject(obj, config);
json = new OldJSONObject(obj, config);
} else if (obj instanceof Iterable || obj instanceof Iterator || ArrayUtil.isArray(obj)) {// 列表
json = new JSONArray(obj, config);
} else {// 对象
json = new JSONObject(obj, config);
json = new OldJSONObject(obj, config);
}
return json;

View File

@@ -21,7 +21,7 @@ import org.dromara.hutool.core.date.format.GlobalCustomFormat;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.json.JSONConfig;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.OldJSONObject;
import org.dromara.hutool.json.JSONUtil;
import java.io.Serializable;
@@ -40,7 +40,7 @@ public class Claims implements Serializable {
// 时间使用秒级时间戳表示
private final JSONConfig CONFIG = JSONConfig.of().setDateFormat(GlobalCustomFormat.FORMAT_SECONDS);
private JSONObject claimJSON;
private OldJSONObject claimJSON;
/**
* 增加Claims属性如果属性值为{@code null},则移除这个属性
@@ -86,7 +86,7 @@ public class Claims implements Serializable {
*
* @return JSON字符串
*/
public JSONObject getClaimsJson() {
public OldJSONObject getClaimsJson() {
init();
return this.claimJSON;
}
@@ -109,7 +109,7 @@ public class Claims implements Serializable {
private void init(){
if(null == this.claimJSON){
this.claimJSON = new JSONObject(CONFIG);
this.claimJSON = new OldJSONObject(CONFIG);
}
}
}

View File

@@ -24,7 +24,7 @@ import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.text.split.SplitUtil;
import org.dromara.hutool.core.util.CharsetUtil;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.OldJSONObject;
import org.dromara.hutool.json.jwt.signers.AlgorithmUtil;
import org.dromara.hutool.json.jwt.signers.JWTSigner;
import org.dromara.hutool.json.jwt.signers.JWTSignerUtil;
@@ -203,7 +203,7 @@ public class JWT implements RegisteredPayload<JWT> {
*
* @return 头信息
*/
public JSONObject getHeaders() {
public OldJSONObject getHeaders() {
return this.header.getClaimsJson();
}
@@ -265,7 +265,7 @@ public class JWT implements RegisteredPayload<JWT> {
*
* @return 载荷信息
*/
public JSONObject getPayloads() {
public OldJSONObject getPayloads() {
return this.payload.getClaimsJson();
}

View File

@@ -85,12 +85,12 @@ public class JSONObjectMapper {
}
/**
* 将给定对象转换为{@link JSONObject}
* 将给定对象转换为{@link OldJSONObject}
*
* @param jsonObject 目标{@link JSONObject}
* @param jsonObject 目标{@link OldJSONObject}
*/
@SuppressWarnings("rawtypes")
public void mapTo(final JSONObject jsonObject) {
public void mapTo(final OldJSONObject jsonObject) {
final Object source = this.source;
if (null == source) {
return;
@@ -153,10 +153,10 @@ public class JSONObjectMapper {
* 从{@link ResourceBundle}转换
*
* @param bundle ResourceBundle
* @param jsonObject {@link JSONObject}
* @param jsonObject {@link OldJSONObject}
* @since 5.3.1
*/
private void mapFromResourceBundle(final ResourceBundle bundle, final JSONObject jsonObject) {
private void mapFromResourceBundle(final ResourceBundle bundle, final OldJSONObject jsonObject) {
final Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()) {
final String key = keys.nextElement();
@@ -170,9 +170,9 @@ public class JSONObjectMapper {
* 从字符串转换
*
* @param source JSON字符串
* @param jsonObject {@link JSONObject}
* @param jsonObject {@link OldJSONObject}
*/
private void mapFromStr(final CharSequence source, final JSONObject jsonObject) {
private void mapFromStr(final CharSequence source, final OldJSONObject jsonObject) {
final String jsonStr = StrUtil.trim(source);
if (StrUtil.startWith(jsonStr, '<')) {
// 可能为XML
@@ -188,9 +188,9 @@ public class JSONObjectMapper {
*
* @param x JSONTokener
* @param config JSON配置
* @param jsonObject {@link JSONObject}
* @param jsonObject {@link OldJSONObject}
*/
private void mapFromTokener(final JSONTokener x, final JSONConfig config, final JSONObject jsonObject) {
private void mapFromTokener(final JSONTokener x, final JSONConfig config, final OldJSONObject jsonObject) {
JSONParser.of(x, config).setPredicate(this.predicate).parseTo(jsonObject);
}
@@ -198,9 +198,9 @@ public class JSONObjectMapper {
* 从Record转换
*
* @param record Record对象
* @param jsonObject {@link JSONObject}
* @param jsonObject {@link OldJSONObject}
*/
private void mapFromRecord(final Object record, final JSONObject jsonObject) {
private void mapFromRecord(final Object record, final OldJSONObject jsonObject) {
final Map.Entry<String, Type>[] components = RecordUtil.getRecordComponents(record.getClass());
String key;
@@ -214,9 +214,9 @@ public class JSONObjectMapper {
* 从Bean转换
*
* @param bean Bean对象
* @param jsonObject {@link JSONObject}
* @param jsonObject {@link OldJSONObject}
*/
private void mapFromBean(final Object bean, final JSONObject jsonObject) {
private void mapFromBean(final Object bean, final OldJSONObject jsonObject) {
final CopyOptions copyOptions = InternalJSONUtil.toCopyOptions(jsonObject.config());
if (null != this.predicate) {
copyOptions.setFieldEditor((entry -> this.predicate.test(

View File

@@ -19,8 +19,7 @@ package org.dromara.hutool.json.mapper;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.*;
import org.dromara.hutool.json.serializer.JSONStringer;
import org.dromara.hutool.json.writer.GlobalValueWriters;
import org.dromara.hutool.json.writer.ValueWriterManager;
import java.io.Serializable;
@@ -82,9 +81,8 @@ public class JSONValueMapper implements Serializable {
// null、JSON、字符串和自定义对象原样存储
if (null == object
// 当用户自定义了对象的字符串表示形式,则保留这个对象
|| null != GlobalValueWriters.get(object)
|| null != ValueWriterManager.getInstance().get(object)
|| object instanceof JSON //
|| object instanceof JSONStringer //
|| object instanceof CharSequence //
|| ObjUtil.isBasicType(object) //
) {
@@ -103,7 +101,7 @@ public class JSONValueMapper implements Serializable {
}
// 默认按照JSONObject对待
return new JSONObject(object, jsonConfig);
return new OldJSONObject(object, jsonConfig);
} catch (final Exception exception) {
return null;
}

View File

@@ -121,7 +121,7 @@ public class JSONParser {
}
switch (tokener.nextClean()) {
case CharUtil.DELIM_START:
nextTo((JSONObject) json);
nextTo((OldJSONObject) json);
break;
case CharUtil.BRACKET_START:
nextTo((JSONArray) json);
@@ -146,7 +146,7 @@ public class JSONParser {
final JSON result;
switch (firstChar) {
case CharUtil.DELIM_START:
final JSONObject jsonObject = new JSONObject(config);
final OldJSONObject jsonObject = new OldJSONObject(config);
nextTo(jsonObject);
result = jsonObject;
break;
@@ -167,7 +167,7 @@ public class JSONParser {
*
* @param jsonObject JSON对象
*/
private void nextTo(final JSONObject jsonObject) {
private void nextTo(final OldJSONObject jsonObject) {
final JSONTokener tokener = this.tokener;
char c;

View File

@@ -17,6 +17,7 @@
package org.dromara.hutool.json.serializer;
import org.dromara.hutool.json.JSON;
import org.dromara.hutool.json.OldJSONObject;
/**
* 序列化接口通过实现此接口实现自定义的对象转换为JSON的操作
@@ -32,7 +33,7 @@ public interface JSONSerializer<V> {
* <ul>
* <li>如果为原始类型,可以转为{@link org.dromara.hutool.json.JSONPrimitive}</li>
* <li>如果是集合或数组类,可以转为{@link org.dromara.hutool.json.JSONArray}</li>
* <li>如果是Bean或键值对类型可以转为{@link org.dromara.hutool.json.JSONObject}</li>
* <li>如果是Bean或键值对类型可以转为{@link OldJSONObject}</li>
* </ul>
*
* @param bean 指定类型对象

View File

@@ -1,47 +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.serializer;
import org.dromara.hutool.core.lang.wrapper.Wrapper;
/**
* {@code JSONString}接口定义了一个{@code toJSONString()}<br>
* 实现此接口的类可以通过实现{@code toJSONString()}方法来改变转JSON字符串的方式。
*
* @author Looly
*
*/
@FunctionalInterface
public interface JSONStringer extends Wrapper<Object> {
/**
* 自定义转JSON字符串的方法
*
* @return JSON字符串
*/
String toJSONString();
/**
* 获取原始的对象默认为this
*
* @return 原始对象
*/
@Override
default Object getRaw() {
return this;
}
}

View File

@@ -161,7 +161,7 @@ public class SerializerManager {
* @param bean 对象
* @return JSONSerializer
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@SuppressWarnings({"rawtypes"})
public JSONSerializer<?> getSerializer(final Object bean) {
for (final MatcherJSONSerializer serializer : this.serializerSet) {
if (serializer.match(bean, null)) {
@@ -254,17 +254,18 @@ public class SerializerManager {
* 注册默认的序列化器和反序列化器
*/
private static void registerDefault() {
SingletonHolder.INSTANCE.register(LocalDate.class, (JSONSerializer<?>) new TemporalAccessorSerializer(LocalDate.class));
SingletonHolder.INSTANCE.register(LocalDate.class, (JSONDeserializer<?>) new TemporalAccessorSerializer(LocalDate.class));
final SerializerManager manager = SingletonHolder.INSTANCE;
manager.register(LocalDate.class, (JSONSerializer<?>) new TemporalAccessorSerializer(LocalDate.class));
manager.register(LocalDate.class, (JSONDeserializer<?>) new TemporalAccessorSerializer(LocalDate.class));
SingletonHolder.INSTANCE.register(LocalTime.class, (JSONSerializer<?>) new TemporalAccessorSerializer(LocalTime.class));
SingletonHolder.INSTANCE.register(LocalTime.class, (JSONDeserializer<?>) new TemporalAccessorSerializer(LocalTime.class));
manager.register(LocalTime.class, (JSONSerializer<?>) new TemporalAccessorSerializer(LocalTime.class));
manager.register(LocalTime.class, (JSONDeserializer<?>) new TemporalAccessorSerializer(LocalTime.class));
SingletonHolder.INSTANCE.register(LocalDateTime.class, (JSONSerializer<?>) new TemporalAccessorSerializer(LocalDateTime.class));
SingletonHolder.INSTANCE.register(LocalDateTime.class, (JSONDeserializer<?>) new TemporalAccessorSerializer(LocalDateTime.class));
manager.register(LocalDateTime.class, (JSONSerializer<?>) new TemporalAccessorSerializer(LocalDateTime.class));
manager.register(LocalDateTime.class, (JSONDeserializer<?>) new TemporalAccessorSerializer(LocalDateTime.class));
SingletonHolder.INSTANCE.register((MatcherJSONSerializer<TimeZone>) TimeZoneSerializer.INSTANCE);
SingletonHolder.INSTANCE.register((MatcherJSONDeserializer<TimeZone>) TimeZoneSerializer.INSTANCE);
manager.register((MatcherJSONSerializer<TimeZone>) TimeZoneSerializer.INSTANCE);
manager.register((MatcherJSONDeserializer<TimeZone>) TimeZoneSerializer.INSTANCE);
}
// endregion
}

View File

@@ -66,12 +66,12 @@ public class TemporalAccessorSerializer implements JSONSerializer<TemporalAccess
@Override
public JSON serialize(final TemporalAccessor bean, final JSONContext context) {
final JSONObject json;
final OldJSONObject json;
final JSON contextJson = context.getContextJson();
if(contextJson instanceof JSONObject){
json = (JSONObject) contextJson;
if(contextJson instanceof OldJSONObject){
json = (OldJSONObject) contextJson;
}else {
json = new JSONObject(7F / 0.75F + 1F, context.config());
json = new OldJSONObject(7F / 0.75F + 1F, context.config());
}
if (bean instanceof LocalDate) {
final LocalDate localDate = (LocalDate) bean;
@@ -112,7 +112,7 @@ public class TemporalAccessorSerializer implements JSONSerializer<TemporalAccess
// TODO JSONArray
// JSONObject
final JSONObject jsonObject = (JSONObject) json;
final OldJSONObject jsonObject = (OldJSONObject) json;
if (LocalDate.class.equals(this.temporalAccessorClass) || LocalDateTime.class.equals(this.temporalAccessorClass)) {
// 年
final Integer year = jsonObject.getInt(YEAR_KEY);

View File

@@ -1,67 +0,0 @@
/*
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.json.writer;
import org.dromara.hutool.core.lang.Assert;
import java.util.*;
/**
* 全局自定义对象写出<br>
* 用户通过此全局定义,可针对某些特殊对象的写出<br>
* 对象定义JSONValueWriter后JSON中将存储原始对象
*
* @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

@@ -1,61 +0,0 @@
/*
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.json.writer;
import org.dromara.hutool.json.JSONException;
import org.dromara.hutool.json.serializer.JSONStringer;
/**
* {@link JSONStringer}的值写出器
*
* @author looly
* @since 6.0.0
*/
public class JSONStringValueWriter implements JSONValueWriter {
/**
* 单例对象
*/
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}按照JSON对象对待此方法输出的JSON字符串不包装引号。<br>
* 如果toJSONString()返回null调用toString()方法并使用双引号包装。
*
* @param writer {@link JSONWriter}
* @param jsonStringer {@link JSONStringer}
*/
@Override
public void write(final JSONWriter writer, final Object jsonStringer) {
final String valueStr;
try {
valueStr = ((JSONStringer)jsonStringer).toJSONString();
} catch (final Exception e) {
throw new JSONException(e);
}
if (null != valueStr) {
writer.writeRaw(valueStr);
} else {
writer.writeQuoteStrValue(jsonStringer.toString());
}
}
}

View File

@@ -316,7 +316,7 @@ public class JSONWriter extends Writer {
final int indent = indentFactor + this.indent;
// 自定义规则
final JSONValueWriter valueWriter = GlobalValueWriters.get(value);
final ValueWriter valueWriter = ValueWriterManager.getInstance().get(value);
if(null != valueWriter){
valueWriter.write(this, value);
return this;

View File

@@ -21,17 +21,12 @@ import java.util.function.Predicate;
/**
* JSON的值自定义写出通过自定义实现此接口实现对象自定义写出字符串形式<br>
* 如自定义的一个CustomBean我只希望输出id的值此时自定义此接口<br>
* 其中{@link JSONValueWriter#test(Object)}负责判断何种对象使用此规则{@link JSONValueWriter#write(JSONWriter, Object)}负责写出规则
*
* <p>
* 注意使用{@link GlobalValueWriters#add(JSONValueWriter)}加入全局转换规则后在JSON对象中自定义对象不会被转换为JSON
* 而是原始对象存在只有在生成JSON字符串时才序列化
* </p>
* 其中{@link ValueWriter#test(Object)}负责判断何种对象使用此规则{@link ValueWriter#write(JSONWriter, Object)}负责写出规则
*
* @author looly
* @since 6.0.0
*/
public interface JSONValueWriter extends Predicate<Object> {
public interface ValueWriter extends Predicate<Object> {
/**
* 使用{@link JSONWriter} 写出对象

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.json.writer;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.json.writer.impl.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* ValueWriter管理器用于管理ValueWriter提供ValueWriter的注册和获取
*
* @author looly
* @since 5.8.0
*/
public class ValueWriterManager {
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
*/
private static class SingletonHolder {
/**
* 静态初始化器由JVM来保证线程安全
*/
private static final ValueWriterManager INSTANCE;
static {
INSTANCE = new ValueWriterManager();
registerDefault();
}
}
/**
* 获得单例的 ValueWriterManager
*
* @return ValueWriterManager
*/
public static ValueWriterManager getInstance() {
return ValueWriterManager.SingletonHolder.INSTANCE;
}
private final List<ValueWriter> valueWriterList;
/**
* 构造
*/
public ValueWriterManager() {
this.valueWriterList = Collections.synchronizedList(new ArrayList<>(6));
}
/**
* 加入自定义的对象值写出规则
*
* @param valueWriter 自定义对象写出实现
*/
public void register(final ValueWriter valueWriter) {
valueWriterList.add(Assert.notNull(valueWriter));
}
/**
* 获取自定义对象值写出规则,后加入的优先
*
* @param value 值,{@code null}表示需要自定义null的输出
* @return 自定义的 {@link ValueWriter}
*/
public ValueWriter get(final Object value) {
if (value instanceof ValueWriter) {
return (ValueWriter) value;
}
final List<ValueWriter> valueWriterList = this.valueWriterList;
ValueWriter valueWriter;
for (int i = valueWriterList.size() - 1 ; i >= 0 ; i--) {
valueWriter = valueWriterList.get(i);
if (valueWriter.test(value)) {
return valueWriter;
}
}
return null;
}
/**
* 注册默认的ValueWriter
*/
private static void registerDefault() {
final ValueWriterManager manager = SingletonHolder.INSTANCE;
// JDK对象最后判断
manager.register(JdkValueWriter.INSTANCE);
manager.register(NumberValueWriter.INSTANCE);
manager.register(DateValueWriter.INSTANCE);
manager.register(BooleanValueWriter.INSTANCE);
}
}

View File

@@ -14,7 +14,10 @@
* limitations under the License.
*/
package org.dromara.hutool.json.writer;
package org.dromara.hutool.json.writer.impl;
import org.dromara.hutool.json.writer.JSONWriter;
import org.dromara.hutool.json.writer.ValueWriter;
/**
* Boolean类型的值写出器
@@ -22,7 +25,7 @@ package org.dromara.hutool.json.writer;
* @author looly
* @since 6.0.0
*/
public class BooleanValueWriter implements JSONValueWriter {
public class BooleanValueWriter implements ValueWriter {
/**
* 单例对象
*/

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.dromara.hutool.json.writer;
package org.dromara.hutool.json.writer.impl;
import org.dromara.hutool.core.convert.ConvertUtil;
import org.dromara.hutool.core.date.DateUtil;
@@ -22,6 +22,8 @@ import org.dromara.hutool.core.date.TemporalAccessorUtil;
import org.dromara.hutool.core.date.format.GlobalCustomFormat;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.json.InternalJSONUtil;
import org.dromara.hutool.json.writer.JSONWriter;
import org.dromara.hutool.json.writer.ValueWriter;
import java.time.MonthDay;
import java.time.temporal.TemporalAccessor;
@@ -35,7 +37,7 @@ import java.util.Date;
* @author looly
* @since 6.0.0
*/
public class DateValueWriter implements JSONValueWriter {
public class DateValueWriter implements ValueWriter {
/**
* 单例对象
*/

View File

@@ -14,12 +14,17 @@
* limitations under the License.
*/
package org.dromara.hutool.json.writer;
package org.dromara.hutool.json.writer.impl;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.reflect.ClassUtil;
import org.dromara.hutool.json.writer.JSONWriter;
import org.dromara.hutool.json.writer.ValueWriter;
import java.sql.SQLException;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.Optional;
@@ -38,7 +43,7 @@ import java.util.Optional;
* @author looly
* @since 6.0.0
*/
public class JdkValueWriter implements JSONValueWriter {
public class JdkValueWriter implements ValueWriter {
/**
* 单例对象
*/
@@ -53,8 +58,14 @@ public class JdkValueWriter implements JSONValueWriter {
return true;
}
// 可转换为JSONObject和JSONArray的对象
if (value instanceof Map
// 自定义写出的跳过
if (value instanceof Number
|| value instanceof Date
|| value instanceof Calendar
|| value instanceof TemporalAccessor
|| value instanceof Boolean
// 可转换为JSONObject和JSONArray的对象
|| value instanceof Map
|| value instanceof Map.Entry
|| value instanceof Iterable
|| ArrayUtil.isArray(value)
@@ -69,6 +80,12 @@ public class JdkValueWriter implements JSONValueWriter {
@Override
public void write(final JSONWriter writer, final Object value) {
writer.writeQuoteStrValue(value.toString());
final String valueStr;
if(value instanceof Class<?>){
valueStr = ((Class<?>) value).getName();
}else{
valueStr = value.toString();
}
writer.writeQuoteStrValue(valueStr);
}
}

View File

@@ -14,11 +14,14 @@
* limitations under the License.
*/
package org.dromara.hutool.json.writer;
package org.dromara.hutool.json.writer.impl;
import org.dromara.hutool.core.math.NumberUtil;
import org.dromara.hutool.json.JSONConfig;
import org.dromara.hutool.json.JSONException;
import org.dromara.hutool.json.writer.JSONWriter;
import org.dromara.hutool.json.writer.NumberWriteMode;
import org.dromara.hutool.json.writer.ValueWriter;
/**
* 数字类型的值写出器
@@ -26,7 +29,7 @@ import org.dromara.hutool.json.JSONException;
* @author looly
* @since 6.0.0
*/
public class NumberValueWriter implements JSONValueWriter {
public class NumberValueWriter implements ValueWriter {
/**
* JS中表示的数字最大值

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
* 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.
@@ -14,27 +14,9 @@
* limitations under the License.
*/
package org.dromara.hutool.json.writer;
/**
* {@link Class}类型的值写出器
* {@link org.dromara.hutool.json.writer.ValueWriter} 实现
*
* @author looly
* @since 6.0.0
* @author Looly
*/
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());
}
}
package org.dromara.hutool.json.writer.impl;

View File

@@ -22,7 +22,7 @@ import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.xml.XmlConstants;
import org.dromara.hutool.json.InternalJSONUtil;
import org.dromara.hutool.json.JSONException;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.OldJSONObject;
import java.util.function.Predicate;
@@ -67,7 +67,7 @@ public class JSONXMLParser {
* @param jo JSONObject
* @throws JSONException 解析异常
*/
public void parseJSONObject(final String xmlStr, final JSONObject jo) throws JSONException {
public void parseJSONObject(final String xmlStr, final OldJSONObject jo) throws JSONException {
final XMLTokener x = new XMLTokener(xmlStr);
while (x.more() && x.skipPast("<")) {
parse(x, jo, null, 0);
@@ -78,16 +78,16 @@ public class JSONXMLParser {
* 扫描XML内容并解析到JSONObject中。
*
* @param x {@link XMLTokener}
* @param context {@link JSONObject}
* @param context {@link OldJSONObject}
* @param name 标签名null表示从根标签开始解析
* @param currentNestingDepth 当前层级
* @return {@code true}表示解析完成
* @throws JSONException JSON异常
*/
private boolean parse(final XMLTokener x, final JSONObject context, final String name, final int currentNestingDepth) throws JSONException {
private boolean parse(final XMLTokener x, final OldJSONObject context, final String name, final int currentNestingDepth) throws JSONException {
final char c;
int i;
final JSONObject jsonobject;
final OldJSONObject jsonobject;
String string;
final String tagName;
Object token;
@@ -156,7 +156,7 @@ public class JSONXMLParser {
} else {
tagName = (String) token;
token = null;
jsonobject = new JSONObject();
jsonobject = new OldJSONObject();
final boolean keepStrings = parseConfig.isKeepStrings();
for (; ; ) {
if (token == null) {

View File

@@ -22,7 +22,7 @@ import org.dromara.hutool.core.text.escape.EscapeUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.json.JSONArray;
import org.dromara.hutool.json.JSONException;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.OldJSONObject;
/**
* JSON转XML字符串工具
@@ -70,13 +70,13 @@ public class JSONXMLSerializer {
}
final StringBuilder sb = new StringBuilder();
if (object instanceof JSONObject) {
if (object instanceof OldJSONObject) {
// Emit <tagName>
appendTag(sb, tagName, false);
// Loop thru the keys.
((JSONObject) object).forEach((key, value) -> {
((OldJSONObject) object).forEach((key, value) -> {
if (ArrayUtil.isArray(value)) {
value = new JSONArray(value);
}

View File

@@ -17,7 +17,7 @@
package org.dromara.hutool.json.xml;
import org.dromara.hutool.json.JSONException;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.OldJSONObject;
/**
* 提供静态方法在XML和JSONObject之间转换
@@ -37,7 +37,7 @@ public class JSONXMLUtil {
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown if there is an errors while parsing the string
*/
public static JSONObject toJSONObject(final String string) throws JSONException {
public static OldJSONObject toJSONObject(final String string) throws JSONException {
return toJSONObject(string, ParseConfig.of());
}
@@ -52,8 +52,8 @@ public class JSONXMLUtil {
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown if there is an errors while parsing the string
*/
public static JSONObject toJSONObject(final String string, final ParseConfig parseConfig) throws JSONException {
return toJSONObject(string, new JSONObject(), parseConfig);
public static OldJSONObject toJSONObject(final String string, final ParseConfig parseConfig) throws JSONException {
return toJSONObject(string, new OldJSONObject(), parseConfig);
}
/**
@@ -67,7 +67,7 @@ public class JSONXMLUtil {
* @throws JSONException 解析异常
* @since 5.3.1
*/
public static JSONObject toJSONObject(final String xmlStr, final JSONObject jo, final ParseConfig parseConfig) throws JSONException {
public static OldJSONObject toJSONObject(final String xmlStr, final OldJSONObject jo, final ParseConfig parseConfig) throws JSONException {
JSONXMLParser.of(parseConfig, null).parseJSONObject(xmlStr, jo);
return jo;
}