mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
fix code
This commit is contained in:
@@ -18,9 +18,7 @@ package org.dromara.hutool.json;
|
||||
|
||||
import org.dromara.hutool.core.bean.path.BeanPath;
|
||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.JSONMapper;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
import org.dromara.hutool.json.support.JSONNodeBeanFactory;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
|
||||
@@ -107,11 +105,70 @@ public interface JSON extends Serializable {
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* </pre>
|
||||
* <p>
|
||||
* 获取表达式对应值后转换为对应类型的值
|
||||
*
|
||||
* @param <T> 返回值类型
|
||||
* @param expression 表达式
|
||||
* @return 对象
|
||||
* @see BeanPath#getValue(Object)
|
||||
* @since 4.0.6
|
||||
*/
|
||||
default <T> T getObjByPath(final String expression) {
|
||||
return getByPath(expression, Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过表达式获取JSON中嵌套的对象<br>
|
||||
* <ol>
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* 表达式栗子:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* </pre>
|
||||
* <p>
|
||||
* 获取表达式对应值后转换为对应类型的值
|
||||
*
|
||||
* @param <T> 返回值类型
|
||||
* @param expression 表达式
|
||||
* @param resultType 返回值类型
|
||||
* @return 对象
|
||||
* @see BeanPath#getValue(Object)
|
||||
*/
|
||||
default <T> T getByPath(final String expression, final Type resultType) {
|
||||
final JSON json = getByPath(expression);
|
||||
if (null == json) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSONMapper.of(config(), null).toBean(json, resultType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过表达式获取JSON中嵌套的JSON对象<br>
|
||||
* <ol>
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* 表达式栗子:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* </pre>
|
||||
*
|
||||
* @param expression 表达式
|
||||
* @return JSON对象
|
||||
* @see BeanPath#getValue(Object)
|
||||
*/
|
||||
default JSON getByPath(final String expression) {
|
||||
return (JSON) BeanPath.of(expression).getValue(this);
|
||||
@@ -142,42 +199,6 @@ public interface JSON extends Serializable {
|
||||
BeanPath.of(expression, new JSONNodeBeanFactory(config())).setValue(this, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过表达式获取JSON中嵌套的对象<br>
|
||||
* <ol>
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* 表达式栗子:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* </pre>
|
||||
* <p>
|
||||
* 获取表达式对应值后转换为对应类型的值
|
||||
*
|
||||
* @param <T> 返回值类型
|
||||
* @param expression 表达式
|
||||
* @param resultType 返回值类型
|
||||
* @return 对象
|
||||
* @see BeanPath#getValue(Object)
|
||||
* @since 4.0.6
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> T getByPath(final String expression, final Type resultType) {
|
||||
final JSON json = getByPath(expression);
|
||||
if (null == json) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final JSONDeserializer<Object> deserializer = TypeAdapterManager.getInstance().getDeserializer(json, resultType);
|
||||
return (T) deserializer.deserialize(json, resultType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化打印JSON,缩进为4个空格
|
||||
*
|
||||
|
@@ -18,12 +18,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.MutableEntry;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.serializer.JSONMapper;
|
||||
import org.dromara.hutool.json.serializer.impl.ArrayTypeAdapter;
|
||||
import org.dromara.hutool.json.serializer.impl.IterTypeAdapter;
|
||||
import org.dromara.hutool.json.writer.JSONWriter;
|
||||
|
||||
import java.util.*;
|
||||
@@ -222,7 +222,7 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <T> T[] toArray(final T[] a) {
|
||||
return (T[]) ArrayConverter.INSTANCE.convert(a.getClass().getComponentType(), this);
|
||||
return (T[]) ArrayTypeAdapter.INSTANCE.deserialize(this, a.getClass().getComponentType());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +232,7 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
* @return 实体类对象
|
||||
*/
|
||||
public Object toArray(final Class<?> arrayClass) {
|
||||
return ArrayConverter.INSTANCE.convert(arrayClass, this);
|
||||
return ArrayTypeAdapter.INSTANCE.deserialize(this, arrayClass.getComponentType());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,8 +243,9 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
* @return {@link ArrayList}
|
||||
* @since 3.0.8
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<T> toList(final Class<T> elementType) {
|
||||
return ConvertUtil.toList(elementType, this);
|
||||
return (List<T>) IterTypeAdapter.INSTANCE.deserialize(this, ArrayList.class, elementType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -161,47 +161,57 @@ public class JSONUtil {
|
||||
if (obj instanceof byte[]) {
|
||||
obj = new ByteArrayInputStream((byte[]) obj);
|
||||
}
|
||||
return (JSONObject) parse(obj, config, predicate);
|
||||
|
||||
final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
|
||||
if (obj instanceof CharSequence) {
|
||||
return (JSONObject) jsonMapper.map((CharSequence) obj);
|
||||
}
|
||||
return jsonMapper.mapObj(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONArray
|
||||
*
|
||||
* @param arrayOrCollection 数组或集合对象
|
||||
* @param obj 数组或集合对象或字符串等
|
||||
* @return JSONArray
|
||||
* @since 3.0.8
|
||||
*/
|
||||
public static JSONArray parseArray(final Object arrayOrCollection) {
|
||||
return parseArray(arrayOrCollection, null);
|
||||
public static JSONArray parseArray(final Object obj) {
|
||||
return parseArray(obj, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONArray
|
||||
*
|
||||
* @param arrayOrCollection 数组或集合对象
|
||||
* @param obj 数组或集合对象
|
||||
* @param config JSON配置
|
||||
* @return JSONArray
|
||||
* @since 5.3.1
|
||||
*/
|
||||
public static JSONArray parseArray(final Object arrayOrCollection, final JSONConfig config) {
|
||||
return parseArray(arrayOrCollection, config, null);
|
||||
public static JSONArray parseArray(final Object obj, final JSONConfig config) {
|
||||
return parseArray(obj, config, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONArray
|
||||
*
|
||||
* @param arrayOrCollection 数组或集合对象
|
||||
* @param obj 数组或集合对象
|
||||
* @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) {
|
||||
if (arrayOrCollection instanceof JSONObject) {
|
||||
public static JSONArray parseArray(final Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
if (obj instanceof JSONObject) {
|
||||
final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
|
||||
return jsonMapper.mapFromJSONObject((JSONObject) arrayOrCollection);
|
||||
return jsonMapper.mapFromJSONObject((JSONObject) obj);
|
||||
}
|
||||
return (JSONArray) parse(arrayOrCollection, config, predicate);
|
||||
|
||||
final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
|
||||
if (obj instanceof CharSequence) {
|
||||
return (JSONArray) jsonMapper.map((CharSequence) obj);
|
||||
}
|
||||
return jsonMapper.mapArray(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,7 +280,7 @@ public class JSONUtil {
|
||||
}
|
||||
// endregion
|
||||
|
||||
// -------------------------------------------------------------------- Read start
|
||||
// region ----- read
|
||||
|
||||
/**
|
||||
* 读取JSON
|
||||
@@ -307,9 +317,9 @@ public class JSONUtil {
|
||||
public static JSONArray readJSONArray(final File file, final Charset charset) throws IORuntimeException {
|
||||
return FileUtil.read(file, charset, JSONUtil::parseArray);
|
||||
}
|
||||
// -------------------------------------------------------------------- Read end
|
||||
// endregion
|
||||
|
||||
// -------------------------------------------------------------------- toString start
|
||||
// region ----- toJsonStr
|
||||
|
||||
/**
|
||||
* 转换为格式化后的JSON字符串
|
||||
@@ -380,9 +390,9 @@ public class JSONUtil {
|
||||
public static JSONObject xmlToJson(final String xml) {
|
||||
return JSONXMLUtil.toJSONObject(xml);
|
||||
}
|
||||
// -------------------------------------------------------------------- toString end
|
||||
// endregion
|
||||
|
||||
// -------------------------------------------------------------------- toBean start
|
||||
// region ----- toBean
|
||||
|
||||
/**
|
||||
* 转为实体类对象
|
||||
@@ -398,20 +408,6 @@ public class JSONUtil {
|
||||
return toBean(json, (Type) clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为实体类对象
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param json JSONObject
|
||||
* @param typeReference {@link TypeReference}类型参考子类,可以获取其泛型参数中的Type类型
|
||||
* @return 实体类对象
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public static <T> T toBean(final Object json, final TypeReference<T> typeReference) {
|
||||
Assert.notNull(typeReference);
|
||||
return toBean(json, typeReference.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为实体类对象
|
||||
*
|
||||
@@ -445,8 +441,9 @@ public class JSONUtil {
|
||||
}
|
||||
return json.toBean(type);
|
||||
}
|
||||
// -------------------------------------------------------------------- toBean end
|
||||
// endregion
|
||||
|
||||
// region ----- toList
|
||||
/**
|
||||
* 将JSONArray字符串转换为Bean的List,默认为ArrayList
|
||||
*
|
||||
@@ -472,6 +469,9 @@ public class JSONUtil {
|
||||
public static <T> List<T> toList(final JSONArray jsonArray, final Class<T> elementType) {
|
||||
return null == jsonArray ? null : jsonArray.toList(elementType);
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region ----- getByPath
|
||||
|
||||
/**
|
||||
* 通过表达式获取JSON中嵌套的对象<br>
|
||||
@@ -489,17 +489,45 @@ public class JSONUtil {
|
||||
* person.friends[5].name
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> 值类型
|
||||
* @param json {@link JSON}
|
||||
* @param expression 表达式
|
||||
* @return 对象
|
||||
* @see JSON#getByPath(String)
|
||||
*/
|
||||
public static JSON getByPath(final JSON json, final String expression) {
|
||||
public static <T> T getObjByPath(final JSON json, final String expression) {
|
||||
return getByPath(json, expression, Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过表达式获取JSON中嵌套的对象<br>
|
||||
* <ol>
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* 表达式栗子:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> 值类型
|
||||
* @param json {@link JSON}
|
||||
* @param expression 表达式
|
||||
* @param type 结果类型
|
||||
* @return 对象
|
||||
* @see JSON#getByPath(String)
|
||||
*/
|
||||
public static <T> T getByPath(final JSON json, final String expression, final Type type) {
|
||||
if ((null == json || StrUtil.isBlank(expression))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return json.getByPath(expression);
|
||||
return json.getByPath(expression, type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -539,6 +567,36 @@ public class JSONUtil {
|
||||
return (T) json.getByPath(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过表达式获取JSON中嵌套的对象<br>
|
||||
* <ol>
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* 表达式栗子:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* </pre>
|
||||
*
|
||||
* @param json {@link JSON}
|
||||
* @param expression 表达式
|
||||
* @return 对象
|
||||
* @see JSON#getByPath(String)
|
||||
*/
|
||||
public static JSON getByPath(final JSON json, final String expression) {
|
||||
if ((null == json || StrUtil.isBlank(expression))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return json.getByPath(expression);
|
||||
}
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* 格式化JSON字符串,此方法并不严格检查JSON的格式正确与否
|
||||
*
|
||||
@@ -567,6 +625,7 @@ public class JSONUtil {
|
||||
return json.isEmpty();
|
||||
}
|
||||
|
||||
// region ----- isType
|
||||
/**
|
||||
* 是否为JSON类型字符串,首尾都为大括号或中括号判定为JSON字符串
|
||||
*
|
||||
@@ -605,4 +664,5 @@ public class JSONUtil {
|
||||
}
|
||||
return StrUtil.isWrap(StrUtil.trim(str), '[', ']');
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
@@ -116,6 +116,9 @@ public class JacksonEngine extends AbstractJSONEngine implements Wrapper<ObjectM
|
||||
// 允许没有引号的字段名(非标准)
|
||||
JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES
|
||||
);
|
||||
mapper.disable(
|
||||
// 空Bean默认转为{}
|
||||
SerializationFeature.FAIL_ON_EMPTY_BEANS);
|
||||
|
||||
// 支持Java8+日期格式
|
||||
registerModule(mapper, "com.fasterxml.jackson.datatype.jsr310.JavaTimeModule");
|
||||
|
@@ -28,7 +28,8 @@ import org.dromara.hutool.json.*;
|
||||
public interface JSONContext {
|
||||
|
||||
/**
|
||||
* 获取当前JSON对象
|
||||
* 获取当前JSON对象<br>
|
||||
* 此对象为在Mapper时预定义的对象,用于指定序列化的JSON类型
|
||||
*
|
||||
* @return JSON对象
|
||||
*/
|
||||
|
@@ -109,7 +109,7 @@ public class JSONMapper implements Serializable {
|
||||
if (json instanceof JSONPrimitive) {
|
||||
return (T) ((JSONPrimitive) json).getValue();
|
||||
}
|
||||
return (T) this;
|
||||
return (T) json;
|
||||
}
|
||||
|
||||
JSONDeserializer<Object> deserializer = null;
|
||||
@@ -149,7 +149,7 @@ public class JSONMapper implements Serializable {
|
||||
public JSONArray mapFromJSONObject(final JSONObject jsonObject) {
|
||||
final JSONArray array = JSONUtil.ofArray(jsonConfig);
|
||||
for (final Map.Entry<String, JSON> entry : jsonObject) {
|
||||
array.add(entry.getValue());
|
||||
array.set(entry);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
@@ -163,6 +163,11 @@ public class JSONMapper implements Serializable {
|
||||
*/
|
||||
public JSON map(final CharSequence source) {
|
||||
final String jsonStr = StrUtil.trim(source);
|
||||
if(StrUtil.isEmpty(jsonStr)){
|
||||
// https://www.rfc-editor.org/rfc/rfc8259#section-7
|
||||
// 未被包装的空串理解为null
|
||||
return null;
|
||||
}
|
||||
if (StrUtil.startWith(jsonStr, '<')) {
|
||||
// 可能为XML
|
||||
final JSONObject jsonObject = JSONUtil.ofObj(jsonConfig);
|
||||
@@ -177,17 +182,65 @@ public class JSONMapper implements Serializable {
|
||||
* 在需要的时候转换映射对象<br>
|
||||
* 包装包括:
|
||||
* <ul>
|
||||
* <li>array or collection =》 JSONArray</li>
|
||||
* <li>map =》 JSONObject</li>
|
||||
* <li>standard property (Double, String, et al) =》 原对象</li>
|
||||
* <li>来自于java包 =》 字符串</li>
|
||||
* <li>其它 =》 尝试包装为JSONObject,否则返回{@code null}</li>
|
||||
* <li>array or collection =》 JSONArray</li>
|
||||
* <li>map =》 JSONObject</li>
|
||||
* <li>standard property (Double, String, et al) =》 原对象</li>
|
||||
* <li>其它 =》 尝试包装为JSONObject,否则返回{@code null}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 被映射的对象
|
||||
* @return 映射后的值,null表示此值需被忽略
|
||||
*/
|
||||
public JSON map(Object obj) {
|
||||
public JSON map(final Object obj) {
|
||||
return mapTo(obj, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在需要的时候转换映射对象<br>
|
||||
* 包装包括:
|
||||
* <ul>
|
||||
* <li>map =》 JSONObject</li>
|
||||
* <li>其它 =》 尝试包装为JSONObject,否则返回{@code null}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 被映射的对象
|
||||
* @return 映射后的值,null表示此值需被忽略
|
||||
*/
|
||||
public JSONObject mapObj(final Object obj) {
|
||||
return mapTo(obj, JSONUtil.ofObj(jsonConfig));
|
||||
}
|
||||
|
||||
/**
|
||||
* 在需要的时候转换映射对象<br>
|
||||
* 包装包括:
|
||||
* <ul>
|
||||
* <li>array or collection =》 JSONArray</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 被映射的对象
|
||||
* @return 映射后的值,null表示此值需被忽略
|
||||
*/
|
||||
public JSONArray mapArray(final Object obj) {
|
||||
return mapTo(obj, JSONUtil.ofArray(jsonConfig));
|
||||
}
|
||||
|
||||
/**
|
||||
* 在需要的时候转换映射对象<br>
|
||||
* 包装包括:
|
||||
* <ul>
|
||||
* <li>array or collection =》 JSONArray</li>
|
||||
* <li>map =》 JSONObject</li>
|
||||
* <li>standard property (Double, String, et al) =》 原对象</li>
|
||||
* <li>其它 =》 尝试包装为JSONObject,否则返回{@code null}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 被映射的对象
|
||||
* @param json 被映射的到的对象,{@code null}表示自动识别
|
||||
* @param <T> JSON类型
|
||||
* @return 映射后的值,null表示此值需被忽略
|
||||
*/
|
||||
@SuppressWarnings({"ReassignedVariable", "unchecked"})
|
||||
private <T extends JSON> T mapTo(Object obj, final T json) {
|
||||
if (null == obj) {
|
||||
return null;
|
||||
}
|
||||
@@ -204,8 +257,15 @@ public class JSONMapper implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
// JSON对象如果与预期结果类型一致,则直接返回
|
||||
if (obj instanceof JSON) {
|
||||
return (JSON) obj;
|
||||
if (null != json) {
|
||||
if (obj.getClass() == json.getClass()) {
|
||||
return (T) obj;
|
||||
}
|
||||
} else {
|
||||
return (T) obj;
|
||||
}
|
||||
}
|
||||
|
||||
final Class<?> clazz = obj.getClass();
|
||||
@@ -226,14 +286,25 @@ public class JSONMapper implements Serializable {
|
||||
throw new JSONException("No deserializer for type: " + obj.getClass());
|
||||
}
|
||||
|
||||
final JSON result;
|
||||
try {
|
||||
return serializer.serialize(obj, new SimpleJSONContext(null, this.jsonConfig));
|
||||
result = serializer.serialize(obj, new SimpleJSONContext(json, this.jsonConfig));
|
||||
} catch (final Exception e) {
|
||||
if (ignoreError) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
if(null == json || result.getClass() == json.getClass()){
|
||||
return (T) result;
|
||||
}
|
||||
|
||||
if(ignoreError){
|
||||
return null;
|
||||
}
|
||||
throw new JSONException("JSON type not match, expect: {}, actual: {}",
|
||||
json.getClass().getName(), result.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -189,7 +189,8 @@ public class TypeAdapterManager {
|
||||
}
|
||||
}
|
||||
|
||||
throw new JSONException("No serializer for type: " + type);
|
||||
// 此处返回null,错误处理在mapper中
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -67,9 +67,19 @@ public class ArrayTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJ
|
||||
|
||||
@Override
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
final int size = json.size();
|
||||
final Class<?> componentType = TypeUtil.getClass(deserializeType).getComponentType();
|
||||
final Object result = Array.newInstance(componentType, size);
|
||||
return deserialize(json, componentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化
|
||||
*
|
||||
* @param json JSON对象
|
||||
* @param componentType 组件类型
|
||||
* @return 数组
|
||||
*/
|
||||
public Object deserialize(final JSON json, final Class<?> componentType) {
|
||||
final Object result = Array.newInstance(componentType, json.size());
|
||||
if (json instanceof JSONObject) {
|
||||
fill((JSONObject) json, result, componentType);
|
||||
} else {
|
||||
@@ -87,10 +97,12 @@ public class ArrayTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJ
|
||||
*/
|
||||
private JSON serializeBytes(final byte[] bytes, final JSONContext context) {
|
||||
final JSONConfig config = context.config();
|
||||
switch (bytes[0]) {
|
||||
case '{':
|
||||
case '[':
|
||||
return JSONParser.of(new JSONTokener(IoUtil.toStream(bytes)), config).parse();
|
||||
if(ArrayUtil.isNotEmpty(bytes)){
|
||||
switch (bytes[0]) {
|
||||
case '{':
|
||||
case '[':
|
||||
return JSONParser.of(new JSONTokener(IoUtil.toStream(bytes)), config).parse();
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/dromara/hutool/issues/2369
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.dromara.hutool.json.serializer.impl;
|
||||
|
||||
import org.dromara.hutool.core.bean.BeanDesc;
|
||||
import org.dromara.hutool.core.bean.BeanUtil;
|
||||
import org.dromara.hutool.core.bean.copier.BeanToMapCopier;
|
||||
import org.dromara.hutool.core.bean.copier.ValueProviderToBeanCopier;
|
||||
@@ -25,11 +26,12 @@ import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.InternalJSONUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONConfig;
|
||||
import org.dromara.hutool.json.JSONObject;
|
||||
import org.dromara.hutool.json.support.JSONObjectValueProvider;
|
||||
import org.dromara.hutool.json.serializer.JSONContext;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.MatcherJSONSerializer;
|
||||
import org.dromara.hutool.json.support.JSONObjectValueProvider;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
@@ -49,13 +51,23 @@ public class BeanTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJS
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
final JSON contextJson = ObjUtil.apply(context, JSONContext::getContextJson);
|
||||
return BeanUtil.isReadableBean(bean.getClass())
|
||||
final BeanDesc beanDesc = BeanUtil.getBeanDesc(bean.getClass());
|
||||
if(beanDesc.isEmpty()){
|
||||
// 空Bean按照Bean对待
|
||||
return true;
|
||||
}
|
||||
|
||||
final boolean isTransparent = ObjUtil.defaultIfNull(
|
||||
ObjUtil.apply(contextJson, JSON::config), JSONConfig::isTransientSupport, true);
|
||||
return beanDesc.isReadable(isTransparent)
|
||||
&& (null == contextJson || contextJson instanceof JSONObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final JSON json, final Type deserializeType) {
|
||||
return json instanceof JSONObject && BeanUtil.isWritableBean(TypeUtil.getClass(deserializeType));
|
||||
return json instanceof JSONObject &&
|
||||
// 空对象转目标对象不限制目标是否可写
|
||||
(json.isEmpty() || BeanUtil.isWritableBean(TypeUtil.getClass(deserializeType)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,9 +84,14 @@ public class BeanTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJS
|
||||
|
||||
@Override
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
final Object target = ConstructorUtil.newInstanceIfPossible(TypeUtil.getClass(deserializeType));
|
||||
if(json.isEmpty()){
|
||||
//issue#3649,对于空对象转目标对象,直接实例化一个空对象
|
||||
return target;
|
||||
}
|
||||
final Copier<Object> copier = new ValueProviderToBeanCopier<>(
|
||||
new JSONObjectValueProvider((JSONObject) json),
|
||||
ConstructorUtil.newInstanceIfPossible(TypeUtil.getClass(deserializeType)),
|
||||
target,
|
||||
deserializeType,
|
||||
InternalJSONUtil.toCopyOptions(json.config())
|
||||
);
|
||||
|
@@ -29,7 +29,6 @@ import org.dromara.hutool.json.serializer.MatcherJSONSerializer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Iterator序列化器,将{@link Iterable}或{@link Iterator}转换为JSONArray
|
||||
@@ -45,7 +44,7 @@ public class IterTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJS
|
||||
|
||||
@Override
|
||||
public boolean match(final Object bean, final JSONContext context) {
|
||||
if(bean instanceof MapWrapper){
|
||||
if (bean instanceof MapWrapper) {
|
||||
return false;
|
||||
}
|
||||
return bean instanceof Iterable || bean instanceof Iterator;
|
||||
@@ -77,10 +76,21 @@ public class IterTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJS
|
||||
|
||||
@Override
|
||||
public Object deserialize(final JSON json, final Type deserializeType) {
|
||||
final Class<?> rawType = TypeUtil.getClass(deserializeType);
|
||||
final Class<?> collectionClass = TypeUtil.getClass(deserializeType);
|
||||
final Type elementType = TypeUtil.getTypeArgument(deserializeType);
|
||||
final Collection<?> result = CollUtil.create(rawType, TypeUtil.getClass(elementType));
|
||||
return deserialize(json, collectionClass, elementType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化
|
||||
*
|
||||
* @param json JSON
|
||||
* @param collectionClass 集合类型
|
||||
* @param elementType 元素类型
|
||||
* @return 反序列化后的集合对象
|
||||
*/
|
||||
public Object deserialize(final JSON json, final Class<?> collectionClass, final Type elementType) {
|
||||
final Collection<?> result = CollUtil.create(collectionClass, TypeUtil.getClass(elementType));
|
||||
|
||||
if (json instanceof JSONObject) {
|
||||
fill((JSONObject) json, result, elementType);
|
||||
@@ -116,9 +126,9 @@ public class IterTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJS
|
||||
* @param elementType 元素类型
|
||||
*/
|
||||
private void fill(final JSONObject json, final Collection<?> result, final Type elementType) {
|
||||
for (final Map.Entry<String, JSON> entry : json) {
|
||||
result.add(entry.getValue().toBean(elementType));
|
||||
}
|
||||
json.forEach((key, value)->{
|
||||
result.add(null == value ? null : value.toBean(elementType));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,8 +139,8 @@ public class IterTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJS
|
||||
* @param elementType 元素类型
|
||||
*/
|
||||
private void fill(final JSONArray json, final Collection<?> result, final Type elementType) {
|
||||
for (final JSON element : json) {
|
||||
result.add(element.toBean(elementType));
|
||||
}
|
||||
json.forEach((element)->{
|
||||
result.add(null == element ? null : element.toBean(elementType));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -73,6 +73,7 @@ public class TemporalTypeAdapter implements MatcherJSONSerializer<TemporalAccess
|
||||
// 如果上下文为JSONObject,转为键值对形式
|
||||
final JSON contextJson = context.getContextJson();
|
||||
if (contextJson instanceof JSONObject) {
|
||||
// 用户只有明确需要转为JSONObject时才进行转换
|
||||
toJSONObject(bean, contextJson.asJSONObject());
|
||||
return contextJson;
|
||||
}
|
||||
@@ -153,8 +154,9 @@ public class TemporalTypeAdapter implements MatcherJSONSerializer<TemporalAccess
|
||||
json.set(MINUTE_KEY, localTime.getMinute());
|
||||
json.set(SECOND_KEY, localTime.getSecond());
|
||||
json.set(NANO_KEY, localTime.getNano());
|
||||
} else{
|
||||
throw new JSONException("Unsupported type: {}", bean.getClass().getName());
|
||||
}
|
||||
throw new JSONException("Unsupported type {}.", bean.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user