mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix code
This commit is contained in:
parent
1b92f58bae
commit
d8a7b9b440
@ -38,6 +38,54 @@ public interface BeanDesc extends Serializable {
|
||||
*/
|
||||
Map<String, PropDesc> getPropMap(final boolean ignoreCase);
|
||||
|
||||
/**
|
||||
* 获取Bean属性数量
|
||||
*
|
||||
* @return 字段数量
|
||||
*/
|
||||
default int size(){
|
||||
return getPropMap(false).size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为空
|
||||
*
|
||||
* @return 是否为空
|
||||
*/
|
||||
default boolean isEmpty(){
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有可读字段,即有getter方法或public字段
|
||||
*
|
||||
* @param checkTransient 是否检查transient字段,true表示检查,false表示不检查
|
||||
* @return 是否有可读字段
|
||||
*/
|
||||
default boolean isReadable(final boolean checkTransient){
|
||||
for (final Map.Entry<String, PropDesc> entry : getPropMap(false).entrySet()) {
|
||||
if (entry.getValue().isReadable(checkTransient)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有可写字段,即有setter方法或public字段
|
||||
*
|
||||
* @param checkTransient 是否检查transient字段,true表示检查,false表示不检查
|
||||
* @return 是否有可写字段
|
||||
*/
|
||||
default boolean isWritable(final boolean checkTransient){
|
||||
for (final Map.Entry<String, PropDesc> entry : getPropMap(false).entrySet()) {
|
||||
if (entry.getValue().isWritable(checkTransient)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字段属性列表
|
||||
*
|
||||
|
@ -311,7 +311,11 @@ public class TypeUtil {
|
||||
* @return {@link ParameterizedType}
|
||||
* @since 4.5.2
|
||||
*/
|
||||
public static ParameterizedType toParameterizedType(final Type type, final int interfaceIndex) {
|
||||
public static ParameterizedType toParameterizedType(Type type, final int interfaceIndex) {
|
||||
if(type instanceof TypeReference){
|
||||
type = ((TypeReference<?>) type).getType();
|
||||
}
|
||||
|
||||
if (type instanceof ParameterizedType) {
|
||||
return (ParameterizedType) type;
|
||||
}
|
||||
|
@ -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);
|
||||
@ -180,14 +185,62 @@ public class JSONMapper implements Serializable {
|
||||
* <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>
|
||||
* </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,11 +97,13 @@ public class ArrayTypeAdapter implements MatcherJSONSerializer<Object>, MatcherJ
|
||||
*/
|
||||
private JSON serializeBytes(final byte[] bytes, final JSONContext context) {
|
||||
final JSONConfig config = context.config();
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,14 +22,25 @@ import org.junit.jupiter.api.Test;
|
||||
import java.util.List;
|
||||
|
||||
public class Issue2377Test {
|
||||
|
||||
@Test
|
||||
void toListTest() {
|
||||
final String jsonStr = "[1,[10,11], \"报表.xlsx\"]";
|
||||
final JSONArray array = JSONUtil.parseArray(jsonStr);
|
||||
final List<Object> paramList = JSONUtil.toList(array, Object.class);
|
||||
Assertions.assertEquals(JSONArray.class, paramList.get(1).getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bytesTest() {
|
||||
final Object[] paramArray = new Object[]{1, new byte[]{10, 11}, "报表.xlsx"};
|
||||
final String paramsStr = JSONUtil.toJsonStr(paramArray);
|
||||
Assertions.assertEquals("[1,[10,11],\"报表.xlsx\"]", paramsStr);
|
||||
|
||||
final List<Object> paramList = JSONUtil.toList(paramsStr, Object.class);
|
||||
final JSONArray array = JSONUtil.parseArray(paramsStr);
|
||||
final List<Object> paramList = JSONUtil.toList(array, Object.class);
|
||||
|
||||
Assertions.assertEquals(JSONArray.class, paramList.get(1).getClass());
|
||||
final String paramBytesStr = JSONUtil.toJsonStr(paramList.get(1));
|
||||
Assertions.assertEquals("[10,11]", paramBytesStr);
|
||||
|
||||
|
@ -24,6 +24,8 @@ public class Issue3051Test {
|
||||
|
||||
@Test
|
||||
public void parseTest() {
|
||||
// 空Bean按照Bean对待,转为空对象
|
||||
// 逻辑见:BeanTypeAdapter
|
||||
final JSONObject jsonObject = JSONUtil.parseObj(new EmptyBean(),
|
||||
JSONConfig.of().setIgnoreError(true));
|
||||
|
||||
@ -32,10 +34,8 @@ public class Issue3051Test {
|
||||
|
||||
@Test
|
||||
public void parseTest2() {
|
||||
Assertions.assertThrows(JSONException.class, ()->{
|
||||
final JSONObject jsonObject = JSONUtil.parseObj(new EmptyBean());
|
||||
Assertions.assertEquals("{}", jsonObject.toString());
|
||||
});
|
||||
}
|
||||
|
||||
@Data
|
||||
|
@ -17,7 +17,9 @@
|
||||
package org.dromara.hutool.json;
|
||||
|
||||
import lombok.Data;
|
||||
import org.dromara.hutool.core.xml.XmlUtil;
|
||||
import org.dromara.hutool.core.collection.ListUtil;
|
||||
import org.dromara.hutool.json.serializer.JSONDeserializer;
|
||||
import org.dromara.hutool.json.serializer.TypeAdapterManager;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -33,8 +35,21 @@ public class Issue3139Test {
|
||||
" </c>\n" +
|
||||
"</r>";
|
||||
|
||||
final JSONObject jsonObject = XmlUtil.xmlToBean(XmlUtil.parseXml(xml).getDocumentElement(), JSONObject.class);
|
||||
final R bean = jsonObject.toBean(R.class);
|
||||
final JSONObject jsonObject = JSONUtil.parseObj(xml);
|
||||
Assertions.assertEquals("{\"r\":{\"c\":{\"s\":1,\"p\":\"str\"}}}", jsonObject.toString());
|
||||
|
||||
final JSONObject r = jsonObject.getJSONObject("r");
|
||||
Assertions.assertEquals("{\"c\":{\"s\":1,\"p\":\"str\"}}", r.toString());
|
||||
|
||||
// R中的c为List,但是JSON中为JSONObject,默认会遍历键值对,此处需要自定义序列化
|
||||
TypeAdapterManager.getInstance().register(R.class, (JSONDeserializer<R>) (json, deserializeType) -> {
|
||||
final R r1 = new R();
|
||||
// c作为一个独立对象放入List中
|
||||
r1.setC(ListUtil.of((C) json.asJSONObject().get("c", C.class)));
|
||||
return r1;
|
||||
});
|
||||
|
||||
final R bean = r.toBean(R.class);
|
||||
Assertions.assertNotNull(bean);
|
||||
|
||||
final List<C> c = bean.getC();
|
||||
|
@ -20,13 +20,25 @@ import lombok.Data;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Issue3649Test {
|
||||
@Test
|
||||
void toEmptyBeanTest() {
|
||||
//issue#3649,对于空对象转目标对象,直接实例化一个空对象
|
||||
// 逻辑见:BeanTypeAdapter
|
||||
final Object bean = JSONUtil.toBean("{}", JSONConfig.of().setIgnoreError(false), EmptyBean.class);
|
||||
Assertions.assertEquals(new EmptyBean(), bean);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toEmptyListTest() {
|
||||
final List<?> bean = JSONUtil.toBean("[]", JSONConfig.of().setIgnoreError(false), List.class);
|
||||
Assertions.assertNotNull(bean);
|
||||
Assertions.assertTrue(bean.isEmpty());
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class EmptyBean {}
|
||||
public static class EmptyBean {
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +172,11 @@ public class JSONArrayTest {
|
||||
final JSONArray array = JSONUtil.parseArray(jsonStr);
|
||||
|
||||
//noinspection SuspiciousToArrayCall
|
||||
final Exam[] list = array.toArray(new Exam[0]);
|
||||
Exam[] list = array.toArray(new Exam[0]);
|
||||
Assertions.assertNotEquals(0, list.length);
|
||||
Assertions.assertSame(Exam.class, list[0].getClass());
|
||||
|
||||
list = (Exam[]) array.toArray(Exam[].class);
|
||||
Assertions.assertNotEquals(0, list.length);
|
||||
Assertions.assertSame(Exam.class, list[0].getClass());
|
||||
}
|
||||
@ -233,8 +237,8 @@ public class JSONArrayTest {
|
||||
public void getByPathTest() {
|
||||
final String jsonStr = "[{\"id\": \"1\",\"name\": \"a\"},{\"id\": \"2\",\"name\": \"b\"}]";
|
||||
final JSONArray jsonArray = JSONUtil.parseArray(jsonStr);
|
||||
assertEquals("b", jsonArray.getByPath("[1].name"));
|
||||
assertEquals("b", JSONUtil.getByPath(jsonArray, "[1].name"));
|
||||
assertEquals("b", jsonArray.getByPath("[1].name", Object.class));
|
||||
assertEquals("b", JSONUtil.getObjByPath(jsonArray, "[1].name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -256,7 +260,7 @@ public class JSONArrayTest {
|
||||
final JSONArray jsonArray = new JSONArray();
|
||||
jsonArray.setValue(0, 1);
|
||||
assertEquals(1, jsonArray.size());
|
||||
assertEquals(1, jsonArray.get(0));
|
||||
assertEquals(1, jsonArray.getObj(0));
|
||||
}
|
||||
|
||||
private static Map<String, String> buildMap(final String id, final String parentId, final String name) {
|
||||
|
@ -619,7 +619,7 @@ public class JSONObjectTest {
|
||||
|
||||
@Test
|
||||
public void createJSONObjectTest() {
|
||||
Assertions.assertThrows(ClassCastException.class, ()->{
|
||||
Assertions.assertThrows(JSONException.class, ()->{
|
||||
// 集合类不支持转为JSONObject
|
||||
JSONUtil.parseObj(new JSONArray(), JSONConfig.of());
|
||||
});
|
||||
|
@ -30,16 +30,16 @@ public class JSONPathTest {
|
||||
@Test
|
||||
public void getByPathTest() {
|
||||
final String json = "[{\"id\":\"1\",\"name\":\"xingming\"},{\"id\":\"2\",\"name\":\"mingzi\"}]";
|
||||
Object value = JSONUtil.parseArray(json).getByPath("[0].name");
|
||||
Object value = JSONUtil.parseArray(json).getByPath("[0].name", Object.class);
|
||||
Assertions.assertEquals("xingming", value);
|
||||
value = JSONUtil.parseArray(json).getByPath("[1].name");
|
||||
value = JSONUtil.parseArray(json).getByPath("[1].name", Object.class);
|
||||
Assertions.assertEquals("mingzi", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getByPathTest2(){
|
||||
final String str = "{'accountId':111}";
|
||||
final JSON json = (JSON) JSONUtil.parse(str);
|
||||
final JSON json = JSONUtil.parse(str);
|
||||
final Long accountId = JSONUtil.getByPath(json, "$.accountId", 0L);
|
||||
Assertions.assertEquals(111L, accountId.longValue());
|
||||
}
|
||||
|
@ -102,20 +102,25 @@ public class JSONUtilTest {
|
||||
*/
|
||||
@Test
|
||||
public void parseNumberToJSONArrayTest() {
|
||||
assertThrows(ClassCastException.class, () -> {
|
||||
assertThrows(JSONException.class, () -> {
|
||||
final JSONArray json = JSONUtil.parseArray(123L);
|
||||
Assertions.assertNotNull(json);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字解析为JSONArray报错
|
||||
* 数字解析为JSONArray报错,忽略错误则返回null
|
||||
*/
|
||||
@Test
|
||||
public void parseNumberToJSONArrayTest2() {
|
||||
Assertions.assertThrows(JSONException.class, ()->{
|
||||
JSONUtil.parseArray(123L,
|
||||
JSONConfig.of().setIgnoreError(false));
|
||||
});
|
||||
|
||||
final JSONArray json = JSONUtil.parseArray(123L,
|
||||
JSONConfig.of().setIgnoreError(true));
|
||||
Assertions.assertNotNull(json);
|
||||
Assertions.assertNull(json);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,7 +140,7 @@ public class JSONUtilTest {
|
||||
@Test
|
||||
public void parseNumberToJSONObjectTest2() {
|
||||
final JSONObject json = JSONUtil.parseObj(123L, JSONConfig.of().setIgnoreError(true));
|
||||
assertEquals(new JSONObject(), json);
|
||||
assertNull(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -341,7 +346,7 @@ public class JSONUtilTest {
|
||||
public void testArrayEntity() {
|
||||
final String jsonStr = JSONUtil.toJsonStr(new ArrayEntity());
|
||||
// a为空的bytes数组,按照空的流对待
|
||||
assertEquals("{\"b\":[0],\"c\":[],\"d\":[],\"e\":[]}", jsonStr);
|
||||
assertEquals("{\"a\":[],\"b\":[0],\"c\":[],\"d\":[],\"e\":[]}", jsonStr);
|
||||
}
|
||||
|
||||
@Data
|
||||
|
@ -26,9 +26,37 @@ import java.util.List;
|
||||
|
||||
public class Pr3067Test {
|
||||
|
||||
final String jsonStr = "[{\"username\":\"a\",\"password\":\"a-password\"}, {\"username\":\"b\",\"password\":\"b-password\"}]";
|
||||
|
||||
@Test
|
||||
void toListTest() {
|
||||
final JSONArray array = JSONUtil.parseArray(jsonStr);
|
||||
final List<TestUser> resultList = array.toList(TestUser.class);
|
||||
Assertions.assertNotNull(resultList);
|
||||
Assertions.assertEquals(2, resultList.size());
|
||||
Assertions.assertEquals("a", resultList.get(0).getUsername());
|
||||
Assertions.assertEquals("a-password", resultList.get(0).getPassword());
|
||||
Assertions.assertEquals("b", resultList.get(1).getUsername());
|
||||
Assertions.assertEquals("b-password", resultList.get(1).getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
void toTypeReferenceTest() {
|
||||
final JSONArray array = JSONUtil.parseArray(jsonStr);
|
||||
final List<TestUser> resultList = array.toBean(new TypeReference<List<TestUser>>() {});
|
||||
|
||||
Assertions.assertNotNull(resultList);
|
||||
Assertions.assertEquals(2, resultList.size());
|
||||
Assertions.assertEquals("a", resultList.get(0).getUsername());
|
||||
Assertions.assertEquals("a-password", resultList.get(0).getPassword());
|
||||
Assertions.assertEquals("b", resultList.get(1).getUsername());
|
||||
Assertions.assertEquals("b-password", resultList.get(1).getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getListByPathTest1() {
|
||||
final JSONObject json = JSONUtil.parseObj(ResourceUtil.readUtf8Str("test_json_path_001.json"));
|
||||
|
||||
final List<TestUser> resultList = json.getByPath("testUserList[1].testArray",
|
||||
new TypeReference<List<TestUser>>() {});
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.dromara.hutool.json.engine;
|
||||
|
||||
import lombok.Data;
|
||||
import org.dromara.hutool.core.date.DateTime;
|
||||
import org.dromara.hutool.core.date.DateUtil;
|
||||
import org.dromara.hutool.core.date.TimeUtil;
|
||||
@ -49,6 +50,11 @@ public class JSONEngineTest {
|
||||
Arrays.stream(engineNames).forEach(this::assertWriteTimeZone);
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeEmptyBeanTest() {
|
||||
Arrays.stream(engineNames).forEach(this::assertEmptyBeanToJson);
|
||||
}
|
||||
|
||||
private void assertWriteDateFormat(final String engineName) {
|
||||
final DateTime date = DateUtil.parse("2024-01-01 01:12:21");
|
||||
final BeanWithDate bean = new BeanWithDate(date, TimeUtil.of(date));
|
||||
@ -96,4 +102,15 @@ public class JSONEngineTest {
|
||||
jsonString = engine.toJsonString(timeZone);
|
||||
Assertions.assertEquals("\"GMT+08:00\"", jsonString);
|
||||
}
|
||||
|
||||
private void assertEmptyBeanToJson(final String engineName){
|
||||
final JSONEngine engine = JSONEngineFactory.createEngine(engineName);
|
||||
final String jsonString = engine.toJsonString(new EmptyBean());
|
||||
Assertions.assertEquals("{}", jsonString);
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class EmptyBean{
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user