This commit is contained in:
Looly 2024-09-19 01:47:21 +08:00
parent c489cc7735
commit bc3f6cf1ee
35 changed files with 296 additions and 576 deletions

View File

@ -454,7 +454,6 @@ public class BeanUtil {
* @param ignoreProperties 不拷贝的的属性列表
* @return 目标对象
*/
@SuppressWarnings("unchecked")
public static <T> T copyProperties(final Object source, final Class<T> tClass, final String... ignoreProperties) {
if (null == source) {
return null;
@ -462,7 +461,7 @@ public class BeanUtil {
if (RecordUtil.isRecord(tClass)) {
// issue#I7EO3U
// 转换record时ignoreProperties无效
return (T) RecordConverter.INSTANCE.convert(tClass, source);
return RecordConverter.INSTANCE.convert(tClass, source);
}
final T target = ConstructorUtil.newInstanceIfPossible(tClass);
return copyProperties(source, target, CopyOptions.of().setIgnoreProperties(ignoreProperties));

View File

@ -1955,7 +1955,7 @@ public class CollUtil {
* @param consumer {@link SerBiConsumer} 遍历的每条数据处理器
* @since 5.4.7
*/
public static <T> void forEach(final Iterable<T> iterable, final SerBiConsumer<T, Integer> consumer) {
public static <T> void forEach(final Iterable<T> iterable, final SerBiConsumer<Integer, T> consumer) {
if (iterable == null) {
return;
}
@ -1969,13 +1969,13 @@ public class CollUtil {
* @param iterator {@link Iterator}
* @param consumer {@link SerBiConsumer} 遍历的每条数据处理器
*/
public static <T> void forEach(final Iterator<T> iterator, final SerBiConsumer<T, Integer> consumer) {
public static <T> void forEach(final Iterator<T> iterator, final SerBiConsumer<Integer, T> consumer) {
if (iterator == null) {
return;
}
int index = 0;
while (iterator.hasNext()) {
consumer.accept(iterator.next(), index);
consumer.accept(index, iterator.next());
index++;
}
}
@ -1987,13 +1987,13 @@ public class CollUtil {
* @param enumeration {@link Enumeration}
* @param consumer {@link SerBiConsumer} 遍历的每条数据处理器
*/
public static <T> void forEach(final Enumeration<T> enumeration, final SerBiConsumer<T, Integer> consumer) {
public static <T> void forEach(final Enumeration<T> enumeration, final SerBiConsumer<Integer, T> consumer) {
if (enumeration == null) {
return;
}
int index = 0;
while (enumeration.hasMoreElements()) {
consumer.accept(enumeration.nextElement(), index);
consumer.accept(index, enumeration.nextElement());
index++;
}
}
@ -2007,13 +2007,13 @@ public class CollUtil {
* @param map {@link Map}
* @param kvConsumer {@link SerConsumer3} 遍历的每条数据处理器
*/
public static <K, V> void forEach(final Map<K, V> map, final SerConsumer3<K, V, Integer> kvConsumer) {
public static <K, V> void forEach(final Map<K, V> map, final SerConsumer3<Integer, K, V> kvConsumer) {
if (map == null) {
return;
}
int index = 0;
for (final Entry<K, V> entry : map.entrySet()) {
kvConsumer.accept(entry.getKey(), entry.getValue(), index);
kvConsumer.accept(index, entry.getKey(), entry.getValue());
index++;
}
}

View File

@ -191,4 +191,21 @@ public class ListWrapper<E> extends SimpleWrapper<List<E>> implements List<E> {
public Stream<E> parallelStream() {
return raw.parallelStream();
}
@Override
public int hashCode() {
return this.raw.hashCode();
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final ListWrapper<?> that = (ListWrapper<?>) obj;
return Objects.equals(raw, that.raw);
}
}

View File

@ -561,10 +561,9 @@ public class ConvertUtil {
* @param defaultValue 默认值
* @return Enum
*/
@SuppressWarnings("unchecked")
public static <E extends Enum<E>> E toEnum(final Class<E> clazz, final Object value, final E defaultValue) {
try {
return (E) EnumConverter.INSTANCE.convert(clazz, value);
return EnumConverter.INSTANCE.convert(clazz, value);
} catch (final Exception ignore) {
return defaultValue;
}

View File

@ -40,6 +40,21 @@ public interface Converter {
*/
Object convert(Type targetType, Object value) throws ConvertException;
/**
* 转换为指定类型<br>
* 如果类型无法确定将读取默认值的类型做为目标类型
*
* @param <T> 目标类型
* @param targetType 目标类型
* @param value 原始值如果对象实现了此接口则value为this
* @return 转换后的值
* @throws ConvertException 转换无法正常完成或转换异常时抛出此异常
*/
@SuppressWarnings("unchecked")
default <T> T convert(final Class<T> targetType, final Object value) throws ConvertException {
return (T) convert((Type) targetType, value);
}
/**
* 转换值为指定类型可选是否不抛异常转换<br>
* 当转换失败时返回默认值
@ -57,9 +72,10 @@ public interface Converter {
/**
* 返回原值的转换器不做转换
*
* @return Converter
*/
static Converter identity(){
static Converter identity() {
return (targetType, value) -> value;
}
}

View File

@ -37,7 +37,7 @@ public class TupleConverter implements Converter {
@Override
public Object convert(final Type targetType, final Object value) throws ConvertException {
final Object[] convert = (Object[]) ArrayConverter.INSTANCE.convert(Object[].class, value);
final Object[] convert = ArrayConverter.INSTANCE.convert(Object[].class, value);
return Tuple.of(convert);
}
}

View File

@ -321,7 +321,7 @@ public class CollUtilTest {
final String[] result = new String[1];
final String a = "a";
CollUtil.forEach(map, (key, value, index) -> {
CollUtil.forEach(map, (index, key, value) -> {
if (a.equals(key)) {
result[0] = value;
}

View File

@ -32,7 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
public class CompositeConverterTest {
@Test
void convertEmptyTest() {
final Object convert = CompositeConverter.getInstance().convert(EmptyBean.class, "");
final EmptyBean convert = CompositeConverter.getInstance().convert(EmptyBean.class, "");
assertNotNull(convert);
assertEquals(new EmptyBean(), convert);
}
@ -45,13 +45,13 @@ public class CompositeConverterTest {
final int a = 454553;
final CompositeConverter compositeConverter = CompositeConverter.getInstance();
CharSequence result = (CharSequence) compositeConverter.convert(CharSequence.class, a);
CharSequence result = compositeConverter.convert(CharSequence.class, a);
assertEquals("454553", result);
//此处做为示例自定义CharSequence转换因为Hutool中已经提供CharSequence转换请尽量不要替换
//替换可能引发关联转换异常例如覆盖CharSequence转换会影响全局
compositeConverter.register(CharSequence.class, new CustomConverter());
result = (CharSequence) compositeConverter.convert(CharSequence.class, a);
result = compositeConverter.convert(CharSequence.class, a);
assertEquals("Custom: 454553", result);
}

View File

@ -131,28 +131,28 @@ public class ConvertTest {
final String a = " 34232";
final Integer aInteger = ConvertUtil.toInt(a);
assertEquals(Integer.valueOf(34232), aInteger);
final int aInt = (int) CompositeConverter.getInstance().convert(int.class, a);
final int aInt = CompositeConverter.getInstance().convert(int.class, a);
assertEquals(34232, aInt);
// 带小数测试
final String b = " 34232.00";
final Integer bInteger = ConvertUtil.toInt(b);
assertEquals(Integer.valueOf(34232), bInteger);
final int bInt = (int) CompositeConverter.getInstance().convert(int.class, b);
final int bInt = CompositeConverter.getInstance().convert(int.class, b);
assertEquals(34232, bInt);
// boolean测试
final boolean c = true;
final Integer cInteger = ConvertUtil.toInt(c);
assertEquals(Integer.valueOf(1), cInteger);
final int cInt = (int) CompositeConverter.getInstance().convert(int.class, c);
final int cInt = CompositeConverter.getInstance().convert(int.class, c);
assertEquals(1, cInt);
// boolean测试
final String d = "08";
final Integer dInteger = ConvertUtil.toInt(d);
assertEquals(Integer.valueOf(8), dInteger);
final int dInt = (int) CompositeConverter.getInstance().convert(int.class, d);
final int dInt = CompositeConverter.getInstance().convert(int.class, d);
assertEquals(8, dInt);
}
@ -176,28 +176,28 @@ public class ConvertTest {
final String a = " 342324545435435";
final Long aLong = ConvertUtil.toLong(a);
assertEquals(Long.valueOf(342324545435435L), aLong);
final long aLong2 = (long) CompositeConverter.getInstance().convert(long.class, a);
final long aLong2 = CompositeConverter.getInstance().convert(long.class, a);
assertEquals(342324545435435L, aLong2);
// 带小数测试
final String b = " 342324545435435.245435435";
final Long bLong = ConvertUtil.toLong(b);
assertEquals(Long.valueOf(342324545435435L), bLong);
final long bLong2 = (long) CompositeConverter.getInstance().convert(long.class, b);
final long bLong2 = CompositeConverter.getInstance().convert(long.class, b);
assertEquals(342324545435435L, bLong2);
// boolean测试
final boolean c = true;
final Long cLong = ConvertUtil.toLong(c);
assertEquals(Long.valueOf(1), cLong);
final long cLong2 = (long) CompositeConverter.getInstance().convert(long.class, c);
final long cLong2 = CompositeConverter.getInstance().convert(long.class, c);
assertEquals(1, cLong2);
// boolean测试
final String d = "08";
final Long dLong = ConvertUtil.toLong(d);
assertEquals(Long.valueOf(8), dLong);
final long dLong2 = (long) CompositeConverter.getInstance().convert(long.class, d);
final long dLong2 = CompositeConverter.getInstance().convert(long.class, d);
assertEquals(8, dLong2);
}

View File

@ -95,11 +95,11 @@ public class ConvertToArrayTest {
//数组转数组测试
final int[] a = new int[]{1,2,3,4};
final long[] result = (long[]) CompositeConverter.getInstance().convert(long[].class, a);
final long[] result = CompositeConverter.getInstance().convert(long[].class, a);
Assertions.assertArrayEquals(new long[]{1L, 2L, 3L, 4L}, result);
//数组转数组测试
final byte[] resultBytes = (byte[]) CompositeConverter.getInstance().convert(byte[].class, a);
final byte[] resultBytes = CompositeConverter.getInstance().convert(byte[].class, a);
Assertions.assertArrayEquals(new byte[]{1, 2, 3, 4}, resultBytes);
//字符串转数组

View File

@ -31,7 +31,7 @@ public class EntryConvertTest {
final KVBean kvBean = new KVBean();
kvBean.setKey("a");
kvBean.setValue(1);
final AbstractMap.SimpleEntry<?, ?> entry = (AbstractMap.SimpleEntry<?, ?>) CompositeConverter.getInstance()
final AbstractMap.SimpleEntry<?, ?> entry = CompositeConverter.getInstance()
.convert(AbstractMap.SimpleEntry.class, kvBean);
Assertions.assertEquals("a", entry.getKey());
@ -42,7 +42,7 @@ public class EntryConvertTest {
void beanToEntryTest2() {
final SingleBean bean = new SingleBean();
bean.setA("1");
final AbstractMap.SimpleEntry<?, ?> entry = (AbstractMap.SimpleEntry<?, ?>) CompositeConverter.getInstance()
final AbstractMap.SimpleEntry<?, ?> entry = CompositeConverter.getInstance()
.convert(AbstractMap.SimpleEntry.class, bean);
Assertions.assertEquals("a", entry.getKey());
@ -53,7 +53,7 @@ public class EntryConvertTest {
void mapToEntryTest() {
final Map<String, Integer> bean = new HashMap<>();
bean.put("a", 1);
final AbstractMap.SimpleEntry<?, ?> entry = (AbstractMap.SimpleEntry<?, ?>) CompositeConverter.getInstance()
final AbstractMap.SimpleEntry<?, ?> entry = CompositeConverter.getInstance()
.convert(AbstractMap.SimpleEntry.class, bean);
Assertions.assertEquals("a", entry.getKey());
@ -63,7 +63,7 @@ public class EntryConvertTest {
@Test
void strToEntryTest() {
final String bean = "a=1";
final AbstractMap.SimpleEntry<?, ?> entry = (AbstractMap.SimpleEntry<?, ?>) CompositeConverter.getInstance()
final AbstractMap.SimpleEntry<?, ?> entry = CompositeConverter.getInstance()
.convert(AbstractMap.SimpleEntry.class, bean);
Assertions.assertEquals("a", entry.getKey());
@ -73,7 +73,7 @@ public class EntryConvertTest {
@Test
void strToEntryTest2() {
final String bean = "a:1";
final AbstractMap.SimpleEntry<?, ?> entry = (AbstractMap.SimpleEntry<?, ?>) CompositeConverter.getInstance()
final AbstractMap.SimpleEntry<?, ?> entry = CompositeConverter.getInstance()
.convert(AbstractMap.SimpleEntry.class, bean);
Assertions.assertEquals("a", entry.getKey());
@ -83,7 +83,7 @@ public class EntryConvertTest {
@Test
void strToEntryTest3() {
final String bean = "a,1";
final AbstractMap.SimpleEntry<?, ?> entry = (AbstractMap.SimpleEntry<?, ?>) CompositeConverter.getInstance()
final AbstractMap.SimpleEntry<?, ?> entry = CompositeConverter.getInstance()
.convert(AbstractMap.SimpleEntry.class, bean);
Assertions.assertEquals("a", entry.getKey());

View File

@ -113,9 +113,9 @@ public final class InternalJSONUtil {
return JSONUtil.parseObj(map).toString();
} else if (value instanceof Collection) {
final Collection<?> coll = (Collection<?>) value;
return new JSONArray(coll).toString();
return JSONUtil.parseArray(coll).toString();
} else if (ArrayUtil.isArray(value)) {
return new JSONArray(value).toString();
return JSONUtil.parseArray(value).toString();
} else {
return quote(value.toString());
}

View File

@ -17,16 +17,12 @@
package org.dromara.hutool.json;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.collection.ListWrapper;
import org.dromara.hutool.core.convert.ConvertUtil;
import org.dromara.hutool.core.convert.impl.ArrayConverter;
import org.dromara.hutool.core.lang.Validator;
import org.dromara.hutool.core.lang.mutable.Mutable;
import org.dromara.hutool.core.lang.mutable.MutableEntry;
import org.dromara.hutool.core.lang.mutable.MutableObj;
import org.dromara.hutool.core.text.StrJoiner;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.mapper.JSONArrayMapper;
import org.dromara.hutool.json.mapper.JSONValueMapper;
import org.dromara.hutool.json.writer.JSONWriter;
import java.util.*;
@ -43,7 +39,7 @@ import java.util.function.Predicate;
*
* @author looly
*/
public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, RandomAccess {
public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Integer>, RandomAccess {
private static final long serialVersionUID = 2664900568717612292L;
/**
@ -51,20 +47,12 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
*/
public static final int DEFAULT_CAPACITY = 10;
/**
* 持有原始数据的List
*/
private List<Object> rawList;
/**
* 配置项
*/
private JSONConfig config;
/**
* 对象转换和包装用于将Java对象和值转换为JSON值
*/
private JSONValueMapper valueMapper;
// region Constructors
// region ----- Constructors
/**
* 构造<br>
@ -105,66 +93,8 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
* @since 4.1.19
*/
public JSONArray(final int initialCapacity, final JSONConfig config) {
this.rawList = new ArrayList<>(initialCapacity);
super(new ArrayList<>(initialCapacity));
this.config = ObjUtil.defaultIfNull(config, JSONConfig::of);
this.valueMapper = JSONValueMapper.of(this.config);
}
/**
* 从对象构造忽略{@code null}的值<br>
* 支持以下类型的参数
*
* <pre>
* 1. 数组
* 2. {@link Iterable}对象
* 3. JSON数组字符串
* </pre>
*
* @param object 数组或集合或JSON数组字符串
* @throws JSONException 非数组或集合
*/
public JSONArray(final Object object) throws JSONException {
this(object, JSONConfig.of());
}
/**
* 从对象构造<br>
* 支持以下类型的参数
*
* <pre>
* 1. 数组
* 2. {@link Iterable}对象
* 3. JSON数组字符串
* </pre>
*
* @param object 数组或集合或JSON数组字符串
* @param jsonConfig JSON选项
* @throws JSONException 非数组或集合
* @since 4.6.5
*/
public JSONArray(final Object object, final JSONConfig jsonConfig) throws JSONException {
this(object, jsonConfig, null);
}
/**
* 从对象构造<br>
* 支持以下类型的参数
*
* <pre>
* 1. 数组
* 2. {@link Iterable}对象
* 3. JSON数组字符串
* </pre>
*
* @param object 数组或集合或JSON数组字符串
* @param jsonConfig JSON选项
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @throws JSONException 非数组或集合
* @since 5.8.0
*/
public JSONArray(final Object object, final JSONConfig jsonConfig, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
this(DEFAULT_CAPACITY, jsonConfig);
JSONArrayMapper.of(object, predicate).mapTo(this);
}
// endregion
@ -173,54 +103,21 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
return this.config;
}
/**
* 设置转为字符串时的日期格式默认为时间戳null值
*
* @param format 格式null表示使用时间戳
* @return this
* @since 4.1.19
*/
public JSONArray setDateFormat(final String format) {
this.config.setDateFormat(format);
return this;
}
/**
* JSONArray转为以{@code separator}为分界符的字符串
*
* @param separator 分界符
* @return a string.
* @throws JSONException If the array contains an invalid number.
*/
public String join(final String separator) throws JSONException {
return StrJoiner.of(separator)
.append(this, InternalJSONUtil::valueToString).toString();
}
@Override
public Object get(final int index) {
Object value = this.rawList.get(index);
if(value instanceof JSONPrimitive){
value = ((JSONPrimitive) value).getValue();
}
return value;
public JSON get(final int index) {
return this.raw.get(index);
}
@Override
public Object getObj(final Integer index, final Object defaultValue) {
return (index < 0 || index >= this.size()) ? defaultValue : this.rawList.get(index);
}
/**
* Append an object value. This increases the array's length by one. <br>
* 加入元素数组长度+1等同于 {@link JSONArray#add(Object)}
*
* @param value 可以是 Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the JSONNull.NULL
* @return this.
* @see #set(Object)
*/
public JSONArray put(final Object value) {
return set(value);
final Object value;
final JSON json = get(index);
if(json instanceof JSONPrimitive){
value = ((JSONPrimitive) json).getValue();
}else {
value = json;
}
return ObjUtil.defaultIfNull(value, defaultValue);
}
/**
@ -232,21 +129,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
* @since 5.2.5
*/
public JSONArray set(final Object value) {
this.add(value);
return this;
}
/**
* 加入或者替换JSONArray中指定Index的值如果index大于JSONArray的长度将在指定index设置值之前的位置填充JSONNull.Null
*
* @param index 位置
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException index &lt; 0 或者非有限的数字
* @see #set(int, Object)
*/
public JSONArray put(final int index, final Object value) throws JSONException {
this.set(index, value);
this.add(config.getConverter().convert(JSON.class, value));
return this;
}
@ -268,36 +151,10 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
return jo;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((rawList == null) ? 0 : rawList.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final JSONArray other = (JSONArray) obj;
if (rawList == null) {
return other.rawList == null;
} else {
return rawList.equals(other.rawList);
}
}
@Override
public Iterator<Object> iterator() {
return rawList.iterator();
public Iterator<JSON> iterator() {
return raw.iterator();
}
/**
@ -309,7 +166,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
* @param type JSON类型
*/
public <T extends JSON> Iterable<T> jsonIter(final Class<T> type) {
final Iterator<Object> iterator = iterator();
final Iterator<JSON> iterator = iterator();
return () -> new Iterator<T>() {
@Override
public boolean hasNext() {
@ -327,26 +184,6 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
};
}
@Override
public int size() {
return rawList.size();
}
@Override
public boolean isEmpty() {
return rawList.isEmpty();
}
@Override
public boolean contains(final Object o) {
return rawList.contains(o);
}
@Override
public Object[] toArray() {
return rawList.toArray();
}
@Override
@SuppressWarnings({"unchecked"})
public <T> T[] toArray(final T[] a) {
@ -354,78 +191,29 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
}
@Override
public boolean add(final Object e) {
return add(e, null);
}
/**
* 增加元素
*
* @param e 元素对象自动根据对象类型转换为JSON中的对象
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @return 是否加入成功
*/
public boolean add(final Object e, final Predicate<Mutable<Object>> predicate) {
return addRaw(valueMapper.map(e), predicate);
}
@Override
public Object remove(final int index) {
return index >= 0 && index < this.size() ? this.rawList.remove(index) : null;
}
@Override
public boolean remove(final Object o) {
return rawList.remove(o);
}
@SuppressWarnings({"NullableProblems", "SlowListContainsAll"})
@Override
public boolean containsAll(final Collection<?> c) {
return rawList.containsAll(c);
}
@Override
public boolean addAll(final Collection<?> c) {
public boolean addAll(final int index, final Collection<? extends JSON> c) {
if (CollUtil.isEmpty(c)) {
return false;
}
for (final Object obj : c) {
this.add(obj);
}
return true;
}
@Override
public boolean addAll(final int index, final Collection<?> c) {
if (CollUtil.isEmpty(c)) {
return false;
}
final ArrayList<Object> list = new ArrayList<>(c.size());
for (final Object object : c) {
if (null == object && config.isIgnoreNullValue()) {
final List<JSON> list = new ArrayList<>(c.size());
for (final JSON json : c) {
if (null == json && config.isIgnoreNullValue()) {
continue;
}
this.add(index);
list.add(valueMapper.map(object));
list.add(json);
}
return rawList.addAll(index, list);
return raw.addAll(index, list);
}
@Override
public boolean removeAll(final Collection<?> c) {
return this.rawList.removeAll(c);
}
@Override
public boolean retainAll(final Collection<?> c) {
return this.rawList.retainAll(c);
}
@Override
public void clear() {
this.rawList.clear();
/**
* 加入或者替换JSONArray中指定Index的值如果index大于JSONArray的长度将在指定index设置值之前的位置填充JSONNull.Null
*
* @param index 位置
* @param element 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return 替换的值即之前的值
*/
public JSON setValue(final int index, final Object element) {
return set(index, config.getConverter().convert(JSON.class, element));
}
/**
@ -436,29 +224,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
* @return 替换的值即之前的值
*/
@Override
public Object set(final int index, final Object element) {
return set(index, element, null);
}
/**
* 加入或者替换JSONArray中指定Index的值如果index大于JSONArray的长度将在指定index设置值之前的位置填充JSONNull.Null
*
* @param index 位置
* @param element 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @param filter 过滤器可以修改值keyindex无法修改{@link Predicate#test(Object)}{@code true}保留null表示全部保留
* @return 替换的值即之前的值
* @since 5.8.0
*/
public Object set(final int index, Object element, final Predicate<MutableEntry<Integer, Object>> filter) {
// 添加前置过滤通过MutablePair实现过滤修改键值对等
if (null != filter) {
final MutableEntry<Integer, Object> pair = new MutableEntry<>(index, element);
if (filter.test(pair)) {
// 使用修改后的值
element = pair.getValue();
}
}
public JSON set(final int index, final JSON element) {
// 越界则追加到指定位置
if (index >= size()) {
add(index, element);
@ -467,11 +233,11 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
if (null == element && config.isIgnoreNullValue()) {
return null;
}
return this.rawList.set(index, valueMapper.map(element));
return this.raw.set(index, element);
}
@Override
public void add(int index, final Object element) {
public void add(int index, final JSON element) {
if (null == element && config.isIgnoreNullValue()) {
return;
}
@ -479,7 +245,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
if (index < 0) {
index = 0;
}
this.rawList.add(index, valueMapper.map(element));
this.raw.add(index, element);
} else {
// issue#3286, 如果用户指定的index太大容易造成Java heap space错误
if (!config.isIgnoreNullValue()) {
@ -495,31 +261,6 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
}
@Override
public int indexOf(final Object o) {
return this.rawList.indexOf(o);
}
@Override
public int lastIndexOf(final Object o) {
return this.rawList.lastIndexOf(o);
}
@Override
public ListIterator<Object> listIterator() {
return this.rawList.listIterator();
}
@Override
public ListIterator<Object> listIterator(final int index) {
return this.rawList.listIterator(index);
}
@Override
public List<Object> subList(final int fromIndex, final int toIndex) {
return this.rawList.subList(fromIndex, toIndex);
}
/**
* 转为Bean数组
*
@ -569,45 +310,15 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
@Override
public void write(final JSONWriter writer) throws JSONException {
final JSONWriter copyWriter = writer.copyOfSub();
copyWriter.beginArray();
CollUtil.forEach(this, (value, index) -> copyWriter.writeField(new MutableEntry<>(index, value)));
copyWriter.end();
writer.beginArray();
CollUtil.forEach(this, (index, value) -> writer.writeField(new MutableEntry<>(index, value)));
writer.end();
}
@Override
public Object clone() throws CloneNotSupportedException {
final JSONArray clone = (JSONArray) super.clone();
clone.config = this.config;
clone.valueMapper = this.valueMapper;
clone.rawList = ObjUtil.clone(this.rawList);
return clone;
}
/**
* 原始添加添加的对象不做任何处理
*
* @param obj 添加的对象
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对值的过滤和修改操作{@code null}表示不过滤{@link Predicate#test(Object)}{@code true}保留
* @return 是否加入成功
* @since 5.8.0
*/
protected boolean addRaw(Object obj, final Predicate<Mutable<Object>> predicate) {
// 添加前置过滤通过MutablePair实现过滤修改键值对等
if (null != predicate) {
final Mutable<Object> mutable = new MutableObj<>(obj);
if (predicate.test(mutable)) {
// 使用修改后的值
obj = mutable.get();
} else {
// 键值对被过滤
return false;
}
}
if (null == obj && config.isIgnoreNullValue()) {
// 忽略空则不添加
return false;
}
return this.rawList.add(obj);
}
}

View File

@ -87,7 +87,7 @@ public interface JSONGetter<K> extends TypeGetter<K> {
if (object instanceof JSON) {
return (JSONArray) object;
}
return new JSONArray(object, config());
return JSONUtil.parseArray(object, config());
}
/**

View File

@ -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.mapper.JSONValueMapper;
import org.dromara.hutool.json.writer.JSONWriter;
import java.util.Arrays;
@ -53,10 +52,6 @@ public class JSONObject extends MapWrapper<String, JSON> implements JSON, JSONGe
* 配置项
*/
private final JSONConfig config;
/**
* 对象转换和包装用于将Java对象和值转换为JSON值
*/
private final JSONValueMapper valueMapper;
/**
* 构造初始容量为 {@link #DEFAULT_CAPACITY}KEY有序
@ -84,7 +79,6 @@ public class JSONObject extends MapWrapper<String, JSON> implements JSON, JSONGe
public JSONObject(final int capacity, final JSONConfig config) {
super(InternalJSONUtil.createRawMap(capacity, config));
this.config = ObjUtil.defaultIfNull(config, JSONConfig::of);
this.valueMapper = JSONValueMapper.of(this.config);
}
@Override
@ -94,10 +88,9 @@ public class JSONObject extends MapWrapper<String, JSON> implements JSON, JSONGe
@Override
public void write(final JSONWriter writer) throws JSONException {
final JSONWriter jsonWriter = writer.copyOfSub();
jsonWriter.beginObj();
this.forEach((key, value) -> jsonWriter.writeField(new MutableEntry<>(key, value)));
jsonWriter.end();
writer.beginObj();
this.forEach((key, value) -> writer.writeField(new MutableEntry<>(key, value)));
writer.end();
}
// region ----- get
@ -225,7 +218,7 @@ public class JSONObject extends MapWrapper<String, JSON> implements JSON, JSONGe
* @throws JSONException 值是无穷数字抛出此异常
*/
public JSONObject set(final String key, final Object value) throws JSONException {
this.put(key, valueMapper.map(value));
this.put(key, this.config.getConverter().convert(JSON.class, value));
return this;
}

View File

@ -23,8 +23,7 @@ import org.dromara.hutool.core.lang.mutable.MutableEntry;
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.mapper.JSONObjectMapper;
import org.dromara.hutool.json.mapper.JSONValueMapper;
import org.dromara.hutool.json.writer.JSONWriter;
import org.dromara.hutool.json.writer.ValueWriter;
import org.dromara.hutool.json.writer.ValueWriterManager;
@ -46,6 +45,7 @@ import java.util.function.Predicate;
public class JSONUtil {
// region ----- of
/**
* 创建JSONObject
*
@ -88,6 +88,7 @@ public class JSONUtil {
// endregion
// region ----- parse
/**
* JSON字符串转JSONObject对象<br>
* 此方法会忽略空值但是对JSON字符串不影响
@ -99,18 +100,6 @@ public class JSONUtil {
return parseObj(obj, JSONConfig.of(), null);
}
/**
* JSON字符串转JSONObject对象
*
* @param obj Bean对象或者Map
* @param ignoreNullValue 是否忽略空值如果source为JSON字符串不忽略空值
* @return JSONObject
* @since 3.0.9
*/
public static JSONObject parseObj(final Object obj, final boolean ignoreNullValue) {
return parseObj(obj, JSONConfig.of().setIgnoreNullValue(ignoreNullValue));
}
/**
* JSON字符串转JSONObject对象<br>
* 此方法会忽略空值但是对JSON字符串不影响
@ -133,9 +122,7 @@ public class JSONUtil {
* @return JSONObject
*/
public static JSONObject parseObj(final Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
final JSONObject jsonObject = new JSONObject(config);
JSONObjectMapper.of(obj, predicate).mapTo(jsonObject);
return jsonObject;
return (JSONObject) parse(obj, config, predicate);
}
/**
@ -146,7 +133,7 @@ public class JSONUtil {
* @since 3.0.8
*/
public static JSONArray parseArray(final Object arrayOrCollection) {
return new JSONArray(arrayOrCollection);
return parseArray(arrayOrCollection, null);
}
/**
@ -158,7 +145,20 @@ public class JSONUtil {
* @since 5.3.1
*/
public static JSONArray parseArray(final Object arrayOrCollection, final JSONConfig config) {
return new JSONArray(arrayOrCollection, config);
return parseArray(arrayOrCollection, config, null);
}
/**
* JSON字符串转JSONArray
*
* @param arrayOrCollection 数组或集合对象
* @param config JSON配置
* @param predicate index和值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@link Predicate#test(Object)}{@code true}保留
* @return JSONArray
* @since 5.3.1
*/
public static JSONArray parseArray(final Object arrayOrCollection, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
return (JSONArray) parse(arrayOrCollection, config, predicate);
}
/**
@ -186,15 +186,34 @@ public class JSONUtil {
* <li>Bean对象转为JSONObject</li>
* </ul>
*
* @param obj 对象
* @param config JSON配置{@code null}使用默认配置
* @param obj 对象
* @param config JSON配置{@code null}使用默认配置
* @return JSONJSONObject or JSONArray
*/
public static JSON parse(final Object obj, final JSONConfig config) {
if (null == config) {
return JSONConverter.INSTANCE.toJSON(obj);
return parse(obj, config, null);
}
/**
* 转换对象为JSON如果用户不配置JSONConfig则JSON的有序与否与传入对象有关<br>
* 支持的对象
* <ul>
* <li>String: 转换为相应的对象</li>
* <li>ArrayIterableIterator转换为JSONArray</li>
* <li>Bean对象转为JSONObject</li>
* </ul>
*
* @param obj 对象
* @param config JSON配置{@code null}使用默认配置
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@link Predicate#test(Object)}{@code true}保留
* @return JSONJSONObject or JSONArray
*/
public static JSON parse(final Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
final JSONValueMapper jsonValueMapper = JSONValueMapper.of(config, predicate);
if (obj instanceof CharSequence) {
return jsonValueMapper.map((CharSequence) obj);
}
return JSONConverter.of(config).toJSON(obj);
return jsonValueMapper.map(obj);
}
/**
@ -219,7 +238,7 @@ public class JSONUtil {
* @throws IORuntimeException IO异常
*/
public static JSON readJSON(final File file, final Charset charset) throws IORuntimeException {
return (JSON) FileUtil.read(file, charset, JSONUtil::parse);
return FileUtil.read(file, charset, JSONUtil::parse);
}
/**

View File

@ -16,14 +16,11 @@
package org.dromara.hutool.json.convert;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.bean.copier.BeanCopier;
import org.dromara.hutool.core.convert.*;
import org.dromara.hutool.core.convert.impl.DateConverter;
import org.dromara.hutool.core.convert.impl.TemporalAccessorConverter;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.map.MapWrapper;
import org.dromara.hutool.core.reflect.ConstructorUtil;
import org.dromara.hutool.core.reflect.TypeReference;
import org.dromara.hutool.core.reflect.TypeUtil;
@ -31,19 +28,16 @@ import org.dromara.hutool.core.reflect.kotlin.KClassUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.*;
import org.dromara.hutool.json.mapper.JSONValueMapper;
import org.dromara.hutool.json.reader.JSONParser;
import org.dromara.hutool.json.reader.JSONTokener;
import org.dromara.hutool.json.serializer.JSONDeserializer;
import org.dromara.hutool.json.serializer.JSONSerializer;
import org.dromara.hutool.json.serializer.SerializerManager;
import org.dromara.hutool.json.serializer.SimpleJSONContext;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.Iterator;
import java.util.Optional;
/**
* JSON转换器实现Object对象转换为{@link JSON}支持的对象
@ -139,47 +133,12 @@ public class JSONConverter implements Converter, Serializable {
* @return 转换后的对象
* @throws JSONException 转换异常
*/
@SuppressWarnings("unchecked")
public JSON toJSON(Object obj) throws JSONException {
public JSON toJSON(final Object obj) throws JSONException {
if (null == obj) {
return null;
}
if (obj instanceof Optional) {
obj = ((Optional<?>) obj).orElse(null);
} else if (obj instanceof Opt) {
obj = ((Opt<?>) obj).getOrNull();
}
if (obj instanceof JSON) {
return (JSON) obj;
}
// 自定义序列化
final JSONSerializer<Object> serializer =
(JSONSerializer<Object>) SerializerManager.getInstance().getSerializer(obj);
if (null != serializer) {
return serializer.serialize(obj, new SimpleJSONContext(null, this.config));
}
if (obj instanceof Number || obj instanceof Boolean) {
// RFC8259规范的原始类型数据
return new JSONPrimitive(obj, config);
}
final JSON json;
if (obj instanceof CharSequence) {
return toJSON((CharSequence) obj);
} else if (obj instanceof MapWrapper) {
// MapWrapper实现了Iterable会被当作JSONArray此处做修正
json = JSONUtil.parseObj(obj, config);
} else if (obj instanceof Iterable || obj instanceof Iterator || ArrayUtil.isArray(obj)) {// 列表
json = JSONUtil.parseArray(obj, config);
} else {// 对象
json = JSONUtil.parseObj(obj, config);
}
return json;
return JSONValueMapper.of(config, null).map(obj);
}
/**
@ -231,7 +190,7 @@ public class JSONConverter implements Converter, Serializable {
// 当目标类型不确定时返回原JSON
final Class<T> rawType = (Class<T>) TypeUtil.getClass(targetType);
if (null == rawType) {
if (null == rawType || rawType.isInstance(json)) {
return (T) json;
//throw new JSONException("Can not get class from type: {}", targetType);
}

View File

@ -30,6 +30,7 @@ import org.dromara.hutool.json.jwt.signers.JWTSigner;
import org.dromara.hutool.json.jwt.signers.JWTSignerUtil;
import org.dromara.hutool.json.jwt.signers.NoneJWTSigner;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.security.Key;
import java.security.KeyPair;
@ -299,7 +300,7 @@ public class JWT implements RegisteredPayload<JWT> {
* @throws ValidateException 传入的类型不匹配payload类型
* @since 6.0.0
*/
public <T> T getPayload(final String propertyName, final Class<T> propertyType) {
public <T> T getPayload(final String propertyName, final Type propertyType) {
return getPayload().getClaimsJson().get(propertyName, propertyType);
}

View File

@ -20,15 +20,11 @@ import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.collection.iter.ArrayIter;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.mutable.MutableEntry;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.json.JSONArray;
import org.dromara.hutool.json.JSONConfig;
import org.dromara.hutool.json.JSONException;
import org.dromara.hutool.json.reader.JSONParser;
import org.dromara.hutool.json.reader.JSONTokener;
import org.dromara.hutool.json.serializer.JSONSerializer;
import org.dromara.hutool.json.serializer.SerializerManager;
import org.dromara.hutool.json.serializer.SimpleJSONContext;
import java.io.InputStream;
import java.io.Reader;
@ -50,7 +46,7 @@ import java.util.function.Predicate;
* @author looly
* @since 6.0.0
*/
public class JSONArrayMapper {
class JSONArrayMapper {
/**
* 创建ArrayMapper
*
@ -88,20 +84,10 @@ public class JSONArrayMapper {
return;
}
// 自定义序列化
final JSONSerializer<Object> serializer = SerializerManager.getInstance().getSerializer(source.getClass());
if (null != serializer) {
serializer.serialize(source, new SimpleJSONContext(jsonArray));
return;
}
if (source instanceof JSONTokener) {
mapFromTokener((JSONTokener) source, JSONConfig.of(), jsonArray);
}if (source instanceof JSONParser) {
((JSONParser)source).parseTo(jsonArray);
} else if (source instanceof CharSequence) {
// JSON字符串
mapFromStr((CharSequence) source, jsonArray);
} else if (source instanceof Reader) {
mapFromTokener(new JSONTokener((Reader) source), jsonArray.config(), jsonArray);
} else if (source instanceof InputStream) {
@ -114,7 +100,7 @@ public class JSONArrayMapper {
// https://github.com/dromara/hutool/issues/2369
// 非标准的二进制流则按照普通数组对待
for (final byte b : bytesSource) {
jsonArray.add(b);
jsonArray.set(b);
}
}
} else {
@ -143,28 +129,16 @@ public class JSONArrayMapper {
if (predicate.test(entry)) {
// 使用修改后的键值对
next = entry.getValue();
jsonArray.add(next);
jsonArray.set(next);
}
}else {
jsonArray.add(next);
jsonArray.set(next);
}
}
}
}
}
/**
* 初始化
*
* @param source JSON字符串
* @param jsonArray {@link JSONArray}
*/
private void mapFromStr(final CharSequence source, final JSONArray jsonArray) {
if (null != source) {
mapFromTokener(new JSONTokener(StrUtil.trim(source)), jsonArray.config(), jsonArray);
}
}
/**
* 初始化
*

View File

@ -27,11 +27,6 @@ import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.json.*;
import org.dromara.hutool.json.reader.JSONParser;
import org.dromara.hutool.json.reader.JSONTokener;
import org.dromara.hutool.json.serializer.JSONSerializer;
import org.dromara.hutool.json.serializer.SerializerManager;
import org.dromara.hutool.json.serializer.SimpleJSONContext;
import org.dromara.hutool.json.xml.JSONXMLParser;
import org.dromara.hutool.json.xml.ParseConfig;
import java.io.InputStream;
import java.io.Reader;
@ -55,9 +50,8 @@ import java.util.function.Predicate;
* </ul>
*
* @author looly
* @since 5.8.0
*/
public class JSONObjectMapper {
class JSONObjectMapper {
/**
* 创建ObjectMapper
@ -96,13 +90,6 @@ public class JSONObjectMapper {
return;
}
// 自定义序列化
final JSONSerializer<Object> serializer = SerializerManager.getInstance().getSerializer(source.getClass());
if (null != serializer) {
serializer.serialize(source, new SimpleJSONContext(jsonObject));
return;
}
if (source instanceof JSONArray) {
// 不支持集合类型转换为JSONObject
throw new JSONException("Unsupported type [{}] to JSONObject!", source.getClass());
@ -122,9 +109,6 @@ public class JSONObjectMapper {
} else if (source instanceof Map.Entry) {
final Map.Entry entry = (Map.Entry) source;
jsonObject.set(ConvertUtil.toStr(entry.getKey()), entry.getValue());
} else if (source instanceof CharSequence) {
// 可能为JSON字符串
mapFromStr((CharSequence) source, jsonObject);
} else if (source instanceof Reader) {
mapFromTokener(new JSONTokener((Reader) source), jsonObject.config(), jsonObject);
} else if (source instanceof InputStream) {
@ -165,23 +149,6 @@ public class JSONObjectMapper {
}
}
/**
* 从字符串转换
*
* @param source JSON字符串
* @param jsonObject {@link JSONObject}
*/
private void mapFromStr(final CharSequence source, final JSONObject jsonObject) {
final String jsonStr = StrUtil.trim(source);
if (StrUtil.startWith(jsonStr, '<')) {
// 可能为XML
//JSONXMLUtil.toJSONObject(jsonStr, jsonObject, ParseConfig.of());
JSONXMLParser.of(ParseConfig.of(), this.predicate).parseJSONObject(jsonStr, jsonObject);
return;
}
mapFromTokener(new JSONTokener(source), jsonObject.config(), jsonObject);
}
/**
* {@link JSONTokener}转换
*

View File

@ -18,10 +18,23 @@ package org.dromara.hutool.json.mapper;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.exception.ExceptionUtil;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.lang.mutable.MutableEntry;
import org.dromara.hutool.core.map.MapWrapper;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.json.*;
import org.dromara.hutool.json.reader.JSONParser;
import org.dromara.hutool.json.reader.JSONTokener;
import org.dromara.hutool.json.serializer.JSONSerializer;
import org.dromara.hutool.json.serializer.SerializerManager;
import org.dromara.hutool.json.serializer.SimpleJSONContext;
import org.dromara.hutool.json.writer.ValueWriterManager;
import org.dromara.hutool.json.xml.JSONXMLParser;
import org.dromara.hutool.json.xml.ParseConfig;
import java.io.Serializable;
import java.util.Optional;
import java.util.function.Predicate;
/**
* 对象和JSON值映射器用于转换对象为JSON对象中的值<br>
@ -45,22 +58,45 @@ public class JSONValueMapper implements Serializable {
/**
* 创建ObjectMapper
*
* @param jsonConfig 来源对象
* @param jsonConfig 来源对象
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@link Predicate#test(Object)}{@code true}保留
* @return ObjectMapper
*/
public static JSONValueMapper of(final JSONConfig jsonConfig) {
return new JSONValueMapper(jsonConfig);
public static JSONValueMapper of(final JSONConfig jsonConfig, final Predicate<MutableEntry<Object, Object>> predicate) {
return new JSONValueMapper(jsonConfig, predicate);
}
private final JSONConfig jsonConfig;
private final Predicate<MutableEntry<Object, Object>> predicate;
/**
* 构造
*
* @param jsonConfig JSON配置
* @param jsonConfig JSON配置
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@link Predicate#test(Object)}{@code true}保留
*/
public JSONValueMapper(final JSONConfig jsonConfig) {
public JSONValueMapper(final JSONConfig jsonConfig, final Predicate<MutableEntry<Object, Object>> predicate) {
this.jsonConfig = jsonConfig;
this.predicate = predicate;
}
/**
* 解析JSON字符串或XML字符串为JSON结构
*
* @param source JSON字符串或XML字符串
* @return JSON对象
*/
public JSON map(final CharSequence source) {
final String jsonStr = StrUtil.trim(source);
if (StrUtil.startWith(jsonStr, '<')) {
// 可能为XML
final JSONObject jsonObject = new JSONObject(jsonConfig);
JSONXMLParser.of(ParseConfig.of(), this.predicate).parseJSONObject(jsonStr, jsonObject);
return jsonObject;
}
return JSONParser.of(new JSONTokener(source), jsonConfig)
.setPredicate(this.predicate)
.parse();
}
/**
@ -74,38 +110,52 @@ public class JSONValueMapper implements Serializable {
* <li>其它 = 尝试包装为JSONObject否则返回{@code null}</li>
* </ul>
*
* @param object 被映射的对象
* @param obj 被映射的对象
* @return 映射后的值null表示此值需被忽略
*/
public JSON map(final Object object) {
if(null == object || object instanceof JSON){
return (JSON) object;
public JSON map(Object obj) {
if (null == obj) {
return null;
}
if(null != ValueWriterManager.getInstance().get(object)){
return new JSONPrimitive(object, jsonConfig);
if (obj instanceof Optional) {
obj = ((Optional<?>) obj).orElse(null);
} else if (obj instanceof Opt) {
obj = ((Opt<?>) obj).getOrNull();
}
// if (object instanceof CharSequence
// || ObjUtil.isBasicType(object)) {
// return new JSONPrimitive(object, jsonConfig);
// }
if (obj instanceof JSON) {
return (JSON) obj;
}
// 自定义序列化
final JSONSerializer<Object> serializer = SerializerManager.getInstance().getSerializer(obj);
if (null != serializer) {
return serializer.serialize(obj, new SimpleJSONContext(null, this.jsonConfig));
}
// 原始类型
if (null != ValueWriterManager.getInstance().get(obj)) {
return new JSONPrimitive(obj, jsonConfig);
}
// 特定对象转换
try {
// JSONArray
if (object instanceof Iterable || ArrayUtil.isArray(object)) {
if (// MapWrapper实现了Iterable会被当作JSONArray此处做修正
!(obj instanceof MapWrapper) &&
(obj instanceof Iterable || ArrayUtil.isArray(obj))) {
final JSONArray jsonArray = new JSONArray(jsonConfig);
JSONArrayMapper.of(object, null).mapTo(jsonArray);
JSONArrayMapper.of(obj, predicate).mapTo(jsonArray);
return jsonArray;
}
// 默认按照JSONObject对待
final JSONObject jsonObject = new JSONObject(jsonConfig);
JSONObjectMapper.of(object, null).mapTo(jsonObject);
JSONObjectMapper.of(obj, predicate).mapTo(jsonObject);
return jsonObject;
} catch (final Exception exception) {
if(jsonConfig.isIgnoreError()){
if (jsonConfig.isIgnoreError()) {
return null;
}
throw ExceptionUtil.wrap(exception, JSONException.class);

View File

@ -232,13 +232,13 @@ public class JSONParser {
return;
} else {
// ,value or value
Object value = nextJSON(CharUtil.COMMA == c ? tokener.nextClean() : c);
JSON value = nextJSON(CharUtil.COMMA == c ? tokener.nextClean() : c);
if (null != predicate) {
// 使用过滤器
final MutableEntry<Object, Object> entry = MutableEntry.of(jsonArray.size(), value);
if (predicate.test(entry)) {
// 使用修改后的键值对
value = entry.getValue();
value = (JSON) entry.getValue();
jsonArray.add(value);
}
} else {

View File

@ -161,11 +161,11 @@ public class SerializerManager {
* @param bean 对象
* @return JSONSerializer
*/
@SuppressWarnings({"rawtypes"})
public JSONSerializer<?> getSerializer(final Object bean) {
for (final MatcherJSONSerializer serializer : this.serializerSet) {
@SuppressWarnings({"unchecked"})
public JSONSerializer<Object> getSerializer(final Object bean) {
for (final MatcherJSONSerializer<?> serializer : this.serializerSet) {
if (serializer.match(bean, null)) {
return serializer;
return (JSONSerializer<Object>) serializer;
}
}
return null;

View File

@ -121,16 +121,6 @@ public class JSONWriter implements Appendable, Flushable, Closeable {
return this.config;
}
/**
* 复制当前对象用于修改配置后写出
* @return JSONWriter
*/
@SuppressWarnings("resource")
public JSONWriter copyOfSub() {
return new JSONWriter(this.appendable, this.indentFactor, this.indent + indentFactor, this.config)
.setPredicate(this.predicate);
}
/**
* JSONObject写出开始默认写出"{"
*
@ -141,6 +131,7 @@ public class JSONWriter implements Appendable, Flushable, Closeable {
append(CharUtil.DELIM_START);
arrayMode = false;
needSeparator = false;
indent += indentFactor;
return this;
}
@ -154,6 +145,7 @@ public class JSONWriter implements Appendable, Flushable, Closeable {
append(CharUtil.BRACKET_START);
arrayMode = true;
needSeparator = false;
indent += indentFactor;
return this;
}
@ -164,6 +156,8 @@ public class JSONWriter implements Appendable, Flushable, Closeable {
*/
@SuppressWarnings("resource")
public JSONWriter end() {
// 结束子缩进
indent -= indentFactor;
// 换行缩进
writeLF().writeSpace(indent);
append(arrayMode ? CharUtil.BRACKET_END : CharUtil.DELIM_END);
@ -215,7 +209,7 @@ public class JSONWriter implements Appendable, Flushable, Closeable {
append(CharUtil.COMMA);
}
// 换行缩进
writeLF().writeSpace(indentFactor + indent);
writeLF().writeSpace(indent);
return writeRaw(InternalJSONUtil.quote(key));
}
@ -346,7 +340,7 @@ public class JSONWriter implements Appendable, Flushable, Closeable {
}
// 换行缩进
//noinspection resource
writeLF().writeSpace(indentFactor + indent);
writeLF().writeSpace(indent);
} else {
//noinspection resource
append(CharUtil.COLON).writeSpace(1);

View File

@ -100,7 +100,7 @@ public class ValueWriterManager {
private static void registerDefault() {
final ValueWriterManager manager = SingletonHolder.INSTANCE;
// JDK对象最后判断
manager.register(JdkValueWriter.INSTANCE);
// manager.register(JdkValueWriter.INSTANCE);
manager.register(NumberValueWriter.INSTANCE);
manager.register(DateValueWriter.INSTANCE);
manager.register(BooleanValueWriter.INSTANCE);

View File

@ -23,6 +23,7 @@ import org.dromara.hutool.core.text.escape.EscapeUtil;
import org.dromara.hutool.json.JSONArray;
import org.dromara.hutool.json.JSONException;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.JSONUtil;
/**
* JSON转XML字符串工具
@ -78,7 +79,7 @@ public class JSONXMLSerializer {
// Loop thru the keys.
((JSONObject) object).forEach((key, value) -> {
if (ArrayUtil.isArray(value)) {
value = new JSONArray(value);
value = JSONUtil.parseArray(value);
}
// Emit content in body
@ -119,7 +120,7 @@ public class JSONXMLSerializer {
}
if (ArrayUtil.isArray(object)) {
object = new JSONArray(object);
object = JSONUtil.parseArray(object);
}
if (object instanceof JSONArray) {

View File

@ -51,7 +51,7 @@ public class Issue3274Test {
Gender(final String enum_name, final String en_Us, final String zh_CN) {
this.enum_name = enum_name;
this.display = new JSONArray("[{\"lang\": \"en-US\",\"value\": \"" + en_Us + "\"},{\"lang\": \"zh-CN\",\"value\": \"" + zh_CN + "\"}]");
this.display = JSONUtil.parseArray("[{\"lang\": \"en-US\",\"value\": \"" + en_Us + "\"},{\"lang\": \"zh-CN\",\"value\": \"" + zh_CN + "\"}]");
}
}
}

View File

@ -17,7 +17,7 @@
package org.dromara.hutool.json;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.json.mapper.JSONObjectMapper;
import org.dromara.hutool.json.mapper.JSONValueMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -27,12 +27,11 @@ public class IssueI9DX5HTest {
@Test
void xmlToJSONTest() {
final String xml = "<GoodMsg>你好</GoodMsg>";
final JSONObjectMapper mapper = JSONObjectMapper.of(xml, entry -> {
final JSONValueMapper mapper = JSONValueMapper.of(JSONConfig.of(), entry -> {
entry.setKey(StrUtil.toUnderlineCase((CharSequence) entry.getKey()));
return true;
});
final JSONObject jsonObject = new JSONObject();
mapper.mapTo(jsonObject);
final JSONObject jsonObject = (JSONObject) mapper.map(xml);
Assertions.assertEquals("{\"good_msg\":\"你好\"}", jsonObject.toString());
}

View File

@ -48,11 +48,11 @@ public class JSONArrayTest {
// JSONObject实现了Iterable接口可以转换为JSONArray
final JSONObject jsonObject = new JSONObject();
JSONArray jsonArray = new JSONArray(jsonObject, JSONConfig.of());
JSONArray jsonArray = JSONUtil.parseArray(jsonObject, JSONConfig.of());
assertEquals(new JSONArray(), jsonArray);
jsonObject.set("key1", "value1");
jsonArray = new JSONArray(jsonObject, JSONConfig.of());
jsonArray = JSONUtil.parseArray(jsonObject, JSONConfig.of());
assertEquals(1, jsonArray.size());
assertEquals("[{\"key1\":\"value1\"}]", jsonArray.toString());
}
@ -70,9 +70,9 @@ public class JSONArrayTest {
final JSONArray array = JSONUtil.ofArray();
// 方法2
// JSONArray array = new JSONArray();
array.add("value1");
array.add("value2");
array.add("value3");
array.set("value1");
array.set("value2");
array.set("value3");
assertEquals(array.get(0), "value1");
}
@ -238,12 +238,12 @@ public class JSONArrayTest {
@Test
public void putToIndexTest() {
JSONArray jsonArray = new JSONArray();
jsonArray.set(3, "test");
jsonArray.setValue(3, "test");
// 默认忽略null值因此空位无值只有一个值
assertEquals(1, jsonArray.size());
jsonArray = new JSONArray(JSONConfig.of().setIgnoreNullValue(false));
jsonArray.set(2, "test");
jsonArray.setValue(2, "test");
// 第三个位置插入值0~2都是null
assertEquals(3, jsonArray.size());
}
@ -252,7 +252,7 @@ public class JSONArrayTest {
@Test
public void putTest2() {
final JSONArray jsonArray = new JSONArray();
jsonArray.put(0, 1);
jsonArray.setValue(0, 1);
assertEquals(1, jsonArray.size());
assertEquals(1, jsonArray.get(0));
}
@ -307,7 +307,7 @@ public class JSONArrayTest {
public void parseFilterTest() {
final String jsonArr = "[{\"id\":111,\"name\":\"test1\"},{\"id\":112,\"name\":\"test2\"}]";
//noinspection MismatchedQueryAndUpdateOfCollection
final JSONArray array = new JSONArray(jsonArr, null, (mutable) -> mutable.get().toString().contains("111"));
final JSONArray array = JSONUtil.parseArray(jsonArr, null, (mutable) -> mutable.get().toString().contains("111"));
assertEquals(1, array.size());
assertTrue(array.getJSONObject(0).containsKey("id"));
}
@ -316,7 +316,7 @@ public class JSONArrayTest {
public void parseFilterEditTest() {
final String jsonArr = "[{\"id\":111,\"name\":\"test1\"},{\"id\":112,\"name\":\"test2\"}]";
//noinspection MismatchedQueryAndUpdateOfCollection
final JSONArray array = new JSONArray(jsonArr, null, (mutable) -> {
final JSONArray array = JSONUtil.parseArray(jsonArr, null, (mutable) -> {
if(mutable.getKey() instanceof Integer){
final JSONObject o = (JSONObject) mutable.getValue();
if ("111".equals(o.getStr("id"))) {

View File

@ -42,7 +42,7 @@ public class JSONNullTest {
" \"device_model\": null,\n" +
" \"device_status_date\": null,\n" +
" \"imsi\": null,\n" +
" \"act_date\": \"2021-07-23T06:23:26.000+00:00\"}", true);
" \"act_date\": \"2021-07-23T06:23:26.000+00:00\"}");
Assertions.assertFalse(bodyjson.containsKey("device_model"));
Assertions.assertFalse(bodyjson.containsKey("device_status_date"));
Assertions.assertFalse(bodyjson.containsKey("imsi"));

View File

@ -313,7 +313,7 @@ public class JSONObjectTest {
userA.setDate(new Date());
userA.setSqs(ListUtil.of(new Seq(null), new Seq("seq2")));
final JSONObject json = JSONUtil.parseObj(userA, false);
final JSONObject json = JSONUtil.parseObj(userA, JSONConfig.of().setIgnoreNullValue(false));
Assertions.assertTrue(json.containsKey("a"));
Assertions.assertTrue(json.getJSONArray("sqs").getJSONObject(0).containsKey("seq"));
@ -328,7 +328,8 @@ public class JSONObjectTest {
bean.setStrValue("strTest");
bean.setTestEnum(TestEnum.TYPE_B);
final JSONObject json = JSONUtil.parseObj(bean, false);
final JSONObject json = JSONUtil.parseObj(bean,
JSONConfig.of().setIgnoreNullValue(false));
// 枚举转换检查更新枚举原样保存在writer时调用toString
Assertions.assertEquals(TestEnum.TYPE_B, json.getObj("testEnum"));
@ -396,7 +397,8 @@ public class JSONObjectTest {
final JSONObject userAJson = JSONUtil.parseObj(userA);
Assertions.assertFalse(userAJson.containsKey("a"));
final JSONObject userAJsonWithNullValue = JSONUtil.parseObj(userA, false);
final JSONObject userAJsonWithNullValue = JSONUtil.parseObj(userA,
JSONConfig.of().setIgnoreNullValue(false));
Assertions.assertTrue(userAJsonWithNullValue.containsKey("a"));
Assertions.assertTrue(userAJsonWithNullValue.containsKey("sqs"));
}

View File

@ -18,6 +18,7 @@ package org.dromara.hutool.json;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.io.resource.ResourceUtil;
import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.json.reader.JSONTokener;
import org.junit.jupiter.api.Test;
@ -29,6 +30,7 @@ public class JSONTokenerTest {
void parseTest() {
final JSONObject jsonObject = JSONUtil.parseObj(ResourceUtil.getUtf8Reader("issue1200.json"));
assertNotNull(jsonObject);
Console.log(jsonObject.toStringPretty());
}
@Test

View File

@ -37,6 +37,7 @@ public class TransientTest {
//noinspection MismatchedQueryAndUpdateOfCollection
final JSONObject jsonObject = JSONUtil.parseObj(detailBill,
JSONConfig.of().setTransientSupport(false));
Assertions.assertEquals("{\"id\":\"3243\",\"bizNo\":\"bizNo\"}", jsonObject.toString());
}

View File

@ -16,12 +16,15 @@
package org.dromara.hutool.json.engine;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.date.DateTime;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.date.TimeUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
public class GsonTest {
/**
* Gson默认缩进两个空格使用\n换行符
@ -54,4 +57,11 @@ public class GsonTest {
Assertions.assertEquals("{\"date\":\"2024-01-01 00:00:00\"}", engine.toJsonString(bean));
}
@Test
void arrayToStringTest() {
final ArrayList<Integer> integers = ListUtil.of(1, 2, 3);
final JSONEngine engine = JSONEngineFactory.createEngine("gson");
final String jsonString = engine.toJsonString(integers);
Assertions.assertEquals("[1,2,3]", jsonString);
}
}

View File

@ -16,13 +16,16 @@
package org.dromara.hutool.json.jwt;
import lombok.Data;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.date.DatePattern;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.reflect.TypeReference;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ByteUtil;
import org.dromara.hutool.json.jwt.signers.AlgorithmUtil;
import org.dromara.hutool.json.jwt.signers.JWTSigner;
import org.dromara.hutool.json.jwt.signers.JWTSignerUtil;
import lombok.Data;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -132,12 +135,12 @@ public class JWTTest {
final List<Integer> list = Arrays.asList(1, 2, 3);
final Integer num = 18;
final String username = "takaki";
final HashMap<String, String> map = new HashMap<>();
final Map<String, String> map = new HashMap<>();
map.put("test1", "1");
map.put("test2", "2");
final Map<String, Object> payload = new HashMap<String, Object>() {
private static final long serialVersionUID = 1L;
{
put("username", username);
put("bean", bean);
@ -155,17 +158,20 @@ public class JWTTest {
final Date dateRes = jwt.getPayload("date", Date.class);
final List<?> listRes = jwt.getPayload("list", List.class);
final Integer numRes = jwt.getPayload("number", Integer.class);
final HashMap<?, ?> mapRes = jwt.getPayload("map", HashMap.class);
final Map<String, String> mapRes = jwt.getPayload("map", new TypeReference<Map<String, String>>(){});
Assertions.assertEquals(bean, beanRes);
Assertions.assertEquals(numRes, num);
Assertions.assertEquals(username, strRes);
Assertions.assertEquals(list, listRes);
Assertions.assertEquals(
StrUtil.wrap(CollUtil.join(list, ","), "[", "]"),
listRes.toString());
final String formattedDate = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
final String formattedRes = DateUtil.format(dateRes, "yyyy-MM-dd HH:mm:ss");
Assertions.assertEquals(formattedDate, formattedRes);
Assertions.assertEquals(map, mapRes);
Assertions.assertEquals(map.get("test1"), mapRes.get("test1"));
Assertions.assertEquals(map.get("test2"), mapRes.get("test2"));
}
@Test()