mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
bcdbf5537c
commit
3ece54bf58
@ -0,0 +1,23 @@
|
||||
package cn.hutool.core.reflect;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 空类型表示
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class NullType implements Type {
|
||||
/**
|
||||
* 单例对象
|
||||
*/
|
||||
public static NullType INSTANCE = new NullType();
|
||||
|
||||
private NullType(){}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Type of null";
|
||||
}
|
||||
}
|
@ -9,25 +9,26 @@ import cn.hutool.core.map.CaseInsensitiveLinkedMap;
|
||||
import cn.hutool.core.map.CaseInsensitiveTreeMap;
|
||||
import cn.hutool.core.math.NumberUtil;
|
||||
import cn.hutool.core.reflect.ClassUtil;
|
||||
import cn.hutool.core.reflect.ConstructorUtil;
|
||||
import cn.hutool.core.reflect.TypeUtil;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.CharUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.serialize.GlobalSerializeMapping;
|
||||
import cn.hutool.json.serialize.JSONDeserializer;
|
||||
import cn.hutool.json.serialize.JSONString;
|
||||
import cn.hutool.json.writer.GlobalValueWriterMapping;
|
||||
import cn.hutool.json.writer.JSONValueWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.SQLException;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
@ -56,9 +57,11 @@ public final class InternalJSONUtil {
|
||||
* @return 包装后的值,null表示此值需被忽略
|
||||
*/
|
||||
static Object wrap(final Object object, final JSONConfig jsonConfig) {
|
||||
if (object == null) {
|
||||
return null;
|
||||
// null和自定义对象原样存储
|
||||
if (null == object || null != InternalJSONUtil.getValueWriter(object)) {
|
||||
return object;
|
||||
}
|
||||
|
||||
if (object instanceof JSON //
|
||||
|| object instanceof JSONString //
|
||||
|| object instanceof CharSequence //
|
||||
@ -369,7 +372,44 @@ public final class InternalJSONUtil {
|
||||
return rawHashMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据值类型获取{@link JSONValueWriter},首先判断对象是否实现了{@link JSONValueWriter}接口<br>
|
||||
* 如果未实现从{@link GlobalValueWriterMapping}中查找全局的writer,否则返回null。
|
||||
*
|
||||
* @param value 值
|
||||
* @param <T> 值类型
|
||||
* @return {@link JSONValueWriter}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> JSONValueWriter<T> getValueWriter(final T value) {
|
||||
if (value instanceof JSONValueWriter) {
|
||||
return (JSONValueWriter<T>) value;
|
||||
}
|
||||
// 全局自定义序列化,支持null的自定义写出
|
||||
return (JSONValueWriter<T>) GlobalValueWriterMapping.get(null == value ? null : value.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据目标类型,获取对应的{@link JSONDeserializer},首先判断是否实现了{@link JSONDeserializer}接口<br>
|
||||
* 如果未实现从{@link GlobalSerializeMapping}中查找全局的{@link JSONDeserializer},否则返回null
|
||||
*
|
||||
* @param targetType 目标类型
|
||||
* @param <T> 目标类型
|
||||
* @return {@link JSONDeserializer}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> JSONDeserializer<T> getDeserializer(final Type targetType) {
|
||||
final Class<T> rawType = (Class<T>) TypeUtil.getClass(targetType);
|
||||
if (null != rawType && JSONDeserializer.class.isAssignableFrom(rawType)) {
|
||||
return (JSONDeserializer<T>) ConstructorUtil.newInstanceIfPossible(rawType);
|
||||
}
|
||||
|
||||
// 全局自定义反序列化(优先级低于实现JSONDeserializer接口)
|
||||
return (JSONDeserializer<T>) GlobalSerializeMapping.getDeserializer(targetType);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* 对所有双引号做转义处理(使用双反斜杠做转义)<br>
|
||||
* 为了能在HTML中较好的显示,会将</转义为<\/<br>
|
||||
|
@ -1,19 +1,11 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.comparator.CompareUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.convert.Converter;
|
||||
import cn.hutool.core.convert.impl.DateConverter;
|
||||
import cn.hutool.core.convert.impl.TemporalAccessorConverter;
|
||||
import cn.hutool.core.reflect.TypeUtil;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.json.convert.JSONConverter;
|
||||
import cn.hutool.json.serialize.JSONString;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* JSON配置项
|
||||
@ -59,35 +51,7 @@ public class JSONConfig implements Serializable {
|
||||
/**
|
||||
* 自定义的类型转换器,用于在getXXX操作中自动转换类型
|
||||
*/
|
||||
private Converter converter = (type, value)->{
|
||||
if(null == value){
|
||||
return null;
|
||||
}
|
||||
if(value instanceof JSONString){
|
||||
// 被JSONString包装的对象,获取其原始类型
|
||||
value = ((JSONString) value).getRaw();
|
||||
}
|
||||
|
||||
final Class<?> rawType = TypeUtil.getClass(type);
|
||||
if(null == rawType){
|
||||
return value;
|
||||
}
|
||||
if(JSON.class.isAssignableFrom(rawType)){
|
||||
return JSONConverter.INSTANCE.toJSON(value);
|
||||
}
|
||||
if(Date.class.isAssignableFrom(rawType) || TemporalAccessor.class.isAssignableFrom(rawType)){
|
||||
// 日期转换,支持自定义日期格式
|
||||
final String format = getDateFormat();
|
||||
if (StrUtil.isNotBlank(format)) {
|
||||
if (Date.class.isAssignableFrom(rawType)) {
|
||||
return new DateConverter(format).convert(type, value);
|
||||
} else {
|
||||
return new TemporalAccessorConverter(format).convert(type, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Convert.convertWithCheck(type, value, null, isIgnoreError());
|
||||
};
|
||||
private Converter converter = JSONConverter.of(this);
|
||||
|
||||
/**
|
||||
* 创建默认的配置项
|
||||
|
@ -2,6 +2,7 @@ package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.lang.mutable.Mutable;
|
||||
import cn.hutool.core.lang.mutable.MutableEntry;
|
||||
import cn.hutool.core.util.CharUtil;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@ -80,7 +81,7 @@ public class JSONParser {
|
||||
|
||||
switch (tokener.nextClean()) {
|
||||
case ';':
|
||||
case ',':
|
||||
case CharUtil.COMMA:
|
||||
if (tokener.nextClean() == '}') {
|
||||
// issue#2380
|
||||
// 尾后逗号(Trailing Commas),JSON中虽然不支持,但是ECMAScript 2017支持,此处做兼容。
|
||||
@ -111,7 +112,7 @@ public class JSONParser {
|
||||
if (x.nextClean() != ']') {
|
||||
x.back();
|
||||
for (; ; ) {
|
||||
if (x.nextClean() == ',') {
|
||||
if (x.nextClean() == CharUtil.COMMA) {
|
||||
x.back();
|
||||
jsonArray.addRaw(null, predicate);
|
||||
} else {
|
||||
@ -119,7 +120,7 @@ public class JSONParser {
|
||||
jsonArray.addRaw(x.nextValue(), predicate);
|
||||
}
|
||||
switch (x.nextClean()) {
|
||||
case ',':
|
||||
case CharUtil.COMMA:
|
||||
if (x.nextClean() == ']') {
|
||||
return;
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ public class JSONTokener {
|
||||
*
|
||||
* @param inputStream InputStream
|
||||
* @param config JSON配置
|
||||
* @throws JSONException JSON异常,包装IO异常
|
||||
*/
|
||||
public JSONTokener(final InputStream inputStream, final JSONConfig config) throws JSONException {
|
||||
this(IoUtil.getUtf8Reader(inputStream), config);
|
||||
@ -89,6 +90,8 @@ public class JSONTokener {
|
||||
|
||||
/**
|
||||
* 将标记回退到第一个字符,重新开始解析新的JSON
|
||||
*
|
||||
* @throws JSONException JSON异常,包装IO异常
|
||||
*/
|
||||
public void back() throws JSONException {
|
||||
if (this.usePrevious || this.index <= 0) {
|
||||
@ -111,6 +114,7 @@ public class JSONTokener {
|
||||
* 源字符串是否有更多的字符
|
||||
*
|
||||
* @return 如果未达到结尾返回true,否则false
|
||||
* @throws JSONException JSON异常,包装IO异常
|
||||
*/
|
||||
public boolean more() throws JSONException {
|
||||
this.next();
|
||||
@ -272,11 +276,11 @@ public class JSONTokener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text up but not including the specified character or the end of line, whichever comes first. <br>
|
||||
* 获得从当前位置直到分隔符(不包括分隔符)或行尾的的所有字符。
|
||||
*
|
||||
* @param delimiter 分隔符
|
||||
* @return 字符串
|
||||
* @throws JSONException JSON异常,包装IO异常
|
||||
*/
|
||||
public String nextTo(final char delimiter) throws JSONException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
@ -297,6 +301,7 @@ public class JSONTokener {
|
||||
*
|
||||
* @param delimiters A set of delimiter characters.
|
||||
* @return A string, trimmed.
|
||||
* @throws JSONException JSON异常,包装IO异常
|
||||
*/
|
||||
public String nextTo(final String delimiters) throws JSONException {
|
||||
char c;
|
||||
@ -314,9 +319,9 @@ public class JSONTokener {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得下一个值,值类型可以是Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the JSONObject.NULL
|
||||
* 获得下一个值,值类型可以是Boolean, Double, Integer, JSONArray, JSONObject, Long, or String
|
||||
*
|
||||
* @return Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the JSONObject.NULL
|
||||
* @return Boolean, Double, Integer, JSONArray, JSONObject, Long, or String
|
||||
* @throws JSONException 语法错误
|
||||
*/
|
||||
public Object nextValue() throws JSONException {
|
||||
@ -360,6 +365,7 @@ public class JSONTokener {
|
||||
*
|
||||
* @param to 需要定位的字符
|
||||
* @return 定位的字符,如果字符未找到返回0
|
||||
* @throws JSONException IO异常
|
||||
*/
|
||||
public char skipTo(final char to) throws JSONException {
|
||||
char c;
|
||||
@ -378,8 +384,8 @@ public class JSONTokener {
|
||||
return c;
|
||||
}
|
||||
} while (c != to);
|
||||
} catch (final IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
} catch (final IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
this.back();
|
||||
return c;
|
||||
@ -396,43 +402,6 @@ public class JSONTokener {
|
||||
return new JSONException(message + this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为 {@link JSONArray}
|
||||
*
|
||||
* @return {@link JSONArray}
|
||||
*/
|
||||
public JSONArray toJSONArray() {
|
||||
final JSONArray jsonArray = new JSONArray(this.config);
|
||||
if (this.nextClean() != '[') {
|
||||
throw this.syntaxError("A JSONArray text must start with '['");
|
||||
}
|
||||
if (this.nextClean() != ']') {
|
||||
this.back();
|
||||
while (true) {
|
||||
if (this.nextClean() == ',') {
|
||||
this.back();
|
||||
jsonArray.add(null);
|
||||
} else {
|
||||
this.back();
|
||||
jsonArray.add(this.nextValue());
|
||||
}
|
||||
switch (this.nextClean()) {
|
||||
case ',':
|
||||
if (this.nextClean() == ']') {
|
||||
return jsonArray;
|
||||
}
|
||||
this.back();
|
||||
break;
|
||||
case ']':
|
||||
return jsonArray;
|
||||
default:
|
||||
throw this.syntaxError("Expected a ',' or ']'");
|
||||
}
|
||||
}
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a printable string of this JSONTokener.
|
||||
*
|
||||
|
@ -10,12 +10,11 @@ import cn.hutool.json.serialize.GlobalSerializeMapping;
|
||||
import cn.hutool.json.serialize.JSONArraySerializer;
|
||||
import cn.hutool.json.serialize.JSONDeserializer;
|
||||
import cn.hutool.json.serialize.JSONObjectSerializer;
|
||||
import cn.hutool.json.writer.JSONValueWriter;
|
||||
import cn.hutool.json.writer.JSONWriter;
|
||||
import cn.hutool.json.xml.JSONXMLUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
@ -296,7 +295,18 @@ public class JSONUtil {
|
||||
* @return JSON字符串
|
||||
* @since 5.7.12
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static String toJsonStr(final Object obj, final JSONConfig jsonConfig) {
|
||||
// 自定义规则,优先级高于全局规则
|
||||
final JSONValueWriter valueWriter = InternalJSONUtil.getValueWriter(obj);
|
||||
if(null != valueWriter){
|
||||
final StringWriter stringWriter = new StringWriter();
|
||||
final JSONWriter jsonWriter = JSONWriter.of(stringWriter, 0, 0, null);
|
||||
// 用户对象自定义实现了JSONValueWriter接口,理解为需要自定义输出
|
||||
valueWriter.write(jsonWriter, obj);
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
if (null == obj) {
|
||||
return null;
|
||||
}
|
||||
|
@ -2,39 +2,33 @@ package cn.hutool.json.convert;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.BeanCopier;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.convert.ConvertException;
|
||||
import cn.hutool.core.convert.Converter;
|
||||
import cn.hutool.core.convert.RegisterConverter;
|
||||
import cn.hutool.core.convert.impl.ArrayConverter;
|
||||
import cn.hutool.core.convert.impl.CollectionConverter;
|
||||
import cn.hutool.core.convert.impl.MapConverter;
|
||||
import cn.hutool.core.convert.impl.*;
|
||||
import cn.hutool.core.map.MapWrapper;
|
||||
import cn.hutool.core.reflect.ConstructorUtil;
|
||||
import cn.hutool.core.reflect.TypeReference;
|
||||
import cn.hutool.core.reflect.TypeUtil;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.json.InternalJSONUtil;
|
||||
import cn.hutool.json.JSON;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONConfig;
|
||||
import cn.hutool.json.JSONException;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.hutool.json.serialize.GlobalSerializeMapping;
|
||||
import cn.hutool.json.*;
|
||||
import cn.hutool.json.serialize.JSONDeserializer;
|
||||
import cn.hutool.json.serialize.JSONString;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* JSON转换器,实现Object对象转换为{@link JSON},支持的对象:
|
||||
* <ul>
|
||||
* <li>String: 转换为相应的对象</li>
|
||||
* <li>Array、Iterable、Iterator:转换为JSONArray</li>
|
||||
* <li>Bean对象:转为JSONObject</li>
|
||||
* <li>任意支持的对象,转换为JSON</li>
|
||||
* <li>JSOn转换为指定对象Bean</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author looly
|
||||
@ -73,27 +67,40 @@ public class JSONConverter implements Converter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Type targetType, final Object obj) throws ConvertException {
|
||||
if (null == obj) {
|
||||
public Object convert(Type targetType, Object value) throws ConvertException {
|
||||
if (null == value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 对象转JSON
|
||||
if (targetType instanceof JSON) {
|
||||
return toJSON(obj);
|
||||
if (value instanceof JSONString) {
|
||||
// 被JSONString包装的对象,获取其原始类型
|
||||
value = ((JSONString) value).getRaw();
|
||||
}
|
||||
|
||||
// JSON转对象
|
||||
if (obj instanceof JSON) {
|
||||
if (value instanceof JSON) {
|
||||
if (targetType instanceof TypeReference) {
|
||||
// 还原原始类型
|
||||
targetType = ((TypeReference<?>) targetType).getType();
|
||||
}
|
||||
return toBean(targetType, (JSON) obj);
|
||||
return toBean(targetType, (JSON) value);
|
||||
}
|
||||
|
||||
// 无法转换
|
||||
throw new JSONException("Can not convert from {}: [{}] to [{}]",
|
||||
obj.getClass().getName(), obj, targetType.getTypeName());
|
||||
// 对象转JSON
|
||||
final Class<?> targetClass = TypeUtil.getClass(targetType);
|
||||
if(null != targetClass){
|
||||
if (JSON.class.isAssignableFrom(targetClass)) {
|
||||
return toJSON(value);
|
||||
}
|
||||
// 自定义日期格式
|
||||
if(Date.class.isAssignableFrom(targetClass) || TemporalAccessor.class.isAssignableFrom(targetClass)){
|
||||
final Object date = toDateWithFormat(targetClass, value);
|
||||
if(null != date){
|
||||
return date;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Convert.convertWithCheck(targetType, value, null, config.isIgnoreError());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,22 +134,30 @@ public class JSONConverter implements Converter {
|
||||
return json;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* JSON转Bean
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param targetType 目标类型,
|
||||
* @param json JSON
|
||||
* @return bean
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T toBean(final Type targetType, final JSON json) {
|
||||
final Class<T> rawType = (Class<T>) TypeUtil.getClass(targetType);
|
||||
if(null != rawType && JSONDeserializer.class.isAssignableFrom(rawType)){
|
||||
return (T) JSONDeserializerConverter.INSTANCE.convert(targetType, json);
|
||||
}
|
||||
|
||||
// 全局自定义反序列化(优先级低于实现JSONDeserializer接口)
|
||||
final JSONDeserializer<?> deserializer = GlobalSerializeMapping.getDeserializer(targetType);
|
||||
// 自定义对象反序列化
|
||||
final JSONDeserializer<Object> deserializer = InternalJSONUtil.getDeserializer(targetType);
|
||||
if (null != deserializer) {
|
||||
return (T) deserializer.deserialize(json);
|
||||
}
|
||||
|
||||
// 其他转换不支持非Class的泛型类型
|
||||
final Class<T> rawType = (Class<T>) TypeUtil.getClass(targetType);
|
||||
if (null == rawType) {
|
||||
throw new JSONException("Can not get class from type: {}", targetType);
|
||||
// 当目标类型不确定时,返回原JSON
|
||||
return (T) json;
|
||||
//throw new JSONException("Can not get class from type: {}", targetType);
|
||||
}
|
||||
// 特殊类型转换,包括Collection、Map、强转、Array等
|
||||
final T result = toSpecial(targetType, rawType, json);
|
||||
@ -164,7 +179,7 @@ public class JSONConverter implements Converter {
|
||||
}
|
||||
|
||||
// 跳过异常时返回null
|
||||
if(json.getConfig().isIgnoreError()){
|
||||
if (json.getConfig().isIgnoreError()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -173,8 +188,6 @@ public class JSONConverter implements Converter {
|
||||
json.getClass().getName(), json, targetType.getTypeName());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* 特殊类型转换<br>
|
||||
* 包括:
|
||||
@ -220,5 +233,18 @@ public class JSONConverter implements Converter {
|
||||
// 表示非需要特殊转换的对象
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object toDateWithFormat(final Class<?> targetClass, final Object value){
|
||||
// 日期转换,支持自定义日期格式
|
||||
final String format = config.getDateFormat();
|
||||
if (StrUtil.isNotBlank(format)) {
|
||||
if (Date.class.isAssignableFrom(targetClass)) {
|
||||
return new DateConverter(format).convert(targetClass, value);
|
||||
} else {
|
||||
return new TemporalAccessorConverter(format).convert(targetClass, value);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// ----------------------------------------------------------- Private method end
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
package cn.hutool.json.convert;
|
||||
|
||||
import cn.hutool.core.convert.AbstractConverter;
|
||||
import cn.hutool.core.convert.ConvertException;
|
||||
import cn.hutool.core.reflect.ConstructorUtil;
|
||||
import cn.hutool.json.JSON;
|
||||
import cn.hutool.json.serialize.JSONDeserializer;
|
||||
|
||||
/**
|
||||
* 实现了{@link JSONDeserializer}接口的Bean对象转换器,用于将指定JSON转换为JSONDeserializer子对象。
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class JSONDeserializerConverter extends AbstractConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final JSONDeserializerConverter INSTANCE = new JSONDeserializerConverter();
|
||||
|
||||
@Override
|
||||
protected Object convertInternal(final Class<?> targetClass, final Object value) {
|
||||
// 自定义反序列化
|
||||
if (value instanceof JSON) {
|
||||
final JSONDeserializer<?> target = (JSONDeserializer<?>) ConstructorUtil.newInstanceIfPossible(targetClass);
|
||||
if (null == target) {
|
||||
throw new ConvertException("Can not instance target: [{}]", targetClass);
|
||||
}
|
||||
return target.deserialize((JSON) value);
|
||||
}
|
||||
|
||||
throw new ConvertException("JSONDeserializer bean must be convert from JSON!");
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package cn.hutool.json.serialize;
|
||||
|
||||
import cn.hutool.core.map.SafeConcurrentHashMap;
|
||||
import cn.hutool.core.reflect.NullType;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.JSON;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
@ -59,19 +61,6 @@ public class GlobalSerializeMapping {
|
||||
putInternal(type, serializer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入自定义的序列化器
|
||||
*
|
||||
* @param type 对象类型
|
||||
* @param serializer 序列化器实现
|
||||
*/
|
||||
synchronized private static void putInternal(final Type type, final JSONSerializer<? extends JSON, ?> serializer) {
|
||||
if (null == serializerMap) {
|
||||
serializerMap = new ConcurrentHashMap<>();
|
||||
}
|
||||
serializerMap.put(type, serializer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入自定义的反序列化器
|
||||
*
|
||||
@ -82,7 +71,7 @@ public class GlobalSerializeMapping {
|
||||
if (null == deserializerMap) {
|
||||
deserializerMap = new ConcurrentHashMap<>();
|
||||
}
|
||||
deserializerMap.put(type, deserializer);
|
||||
deserializerMap.put(ObjUtil.defaultIfNull(type, NullType.INSTANCE), deserializer);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,7 +84,7 @@ public class GlobalSerializeMapping {
|
||||
if (null == serializerMap) {
|
||||
return null;
|
||||
}
|
||||
return serializerMap.get(type);
|
||||
return serializerMap.get(ObjUtil.defaultIfNull(type, NullType.INSTANCE));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,6 +97,19 @@ public class GlobalSerializeMapping {
|
||||
if (null == deserializerMap) {
|
||||
return null;
|
||||
}
|
||||
return deserializerMap.get(type);
|
||||
return deserializerMap.get(ObjUtil.defaultIfNull(type, NullType.INSTANCE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入自定义的序列化器
|
||||
*
|
||||
* @param type 对象类型
|
||||
* @param serializer 序列化器实现
|
||||
*/
|
||||
synchronized private static void putInternal(final Type type, final JSONSerializer<? extends JSON, ?> serializer) {
|
||||
if (null == serializerMap) {
|
||||
serializerMap = new ConcurrentHashMap<>();
|
||||
}
|
||||
serializerMap.put(ObjUtil.defaultIfNull(type, NullType.INSTANCE), serializer);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* JSON序列化和反序列化,提供对象和JSON之间的转换
|
||||
*/
|
||||
package cn.hutool.json.serialize;
|
@ -0,0 +1,44 @@
|
||||
package cn.hutool.json.writer;
|
||||
|
||||
import cn.hutool.core.map.SafeConcurrentHashMap;
|
||||
import cn.hutool.core.reflect.NullType;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 全局自定义对象写出<br>
|
||||
* 用户通过此全局定义,可针对某些特殊对象
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class GlobalValueWriterMapping {
|
||||
|
||||
private static final Map<Type, JSONValueWriter<?>> writerMap;
|
||||
|
||||
static {
|
||||
writerMap = new SafeConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入自定义的对象值写出规则
|
||||
*
|
||||
* @param type 对象类型
|
||||
* @param writer 自定义对象写出实现
|
||||
*/
|
||||
public static void put(final Type type, final JSONValueWriter<?> writer) {
|
||||
writerMap.put(ObjUtil.defaultIfNull(type, NullType.INSTANCE), writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义对象值写出规则
|
||||
*
|
||||
* @param type 对象类型
|
||||
* @return 自定义的 {@link JSONValueWriter}
|
||||
*/
|
||||
public static JSONValueWriter<?> get(final Type type) {
|
||||
return writerMap.get(ObjUtil.defaultIfNull(type, NullType.INSTANCE));
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package cn.hutool.json.writer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* JSON的值自定义写出
|
||||
*
|
||||
@ -14,6 +16,7 @@ public interface JSONValueWriter<T> {
|
||||
*
|
||||
* @param writer {@link JSONWriter}
|
||||
* @param value 被写出的值
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
void write(JSONWriter writer, T value);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.lang.mutable.MutableEntry;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.core.util.CharUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.InternalJSONUtil;
|
||||
import cn.hutool.json.JSON;
|
||||
import cn.hutool.json.JSONConfig;
|
||||
@ -76,7 +77,7 @@ public class JSONWriter extends Writer {
|
||||
this.writer = writer;
|
||||
this.indentFactor = indentFactor;
|
||||
this.indent = indent;
|
||||
this.config = config;
|
||||
this.config = ObjUtil.defaultIfNull(config, JSONConfig.of());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -298,12 +299,21 @@ public class JSONWriter extends Writer {
|
||||
* @param predicate 过滤修改器
|
||||
* @return this
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private JSONWriter writeObjValue(final Object value, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
final int indent = indentFactor + this.indent;
|
||||
|
||||
// 自定义规则
|
||||
final JSONValueWriter valueWriter = InternalJSONUtil.getValueWriter(value);
|
||||
if(null != valueWriter){
|
||||
valueWriter.write(this, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
//noinspection resource
|
||||
writeRaw(StrUtil.NULL);
|
||||
} else if (value instanceof JSON) {
|
||||
}else if (value instanceof JSON) {
|
||||
((JSON) value).write(writer, indentFactor, indent, predicate);
|
||||
} else if (value instanceof Number) {
|
||||
NumberValueWriter.INSTANCE.write(this, (Number) value);
|
||||
|
@ -0,0 +1,67 @@
|
||||
package cn.hutool.json.writer;
|
||||
|
||||
import cn.hutool.core.convert.Converter;
|
||||
import cn.hutool.json.JSONConfig;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.Data;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class GlobalValueWriterMappingTest {
|
||||
|
||||
@Before
|
||||
public void init(){
|
||||
GlobalValueWriterMapping.put(CustomSubBean.class, (JSONValueWriter<CustomSubBean>) (writer, value) -> {
|
||||
writer.writeRaw(String.valueOf(value.getId()));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customWriteTest(){
|
||||
final CustomSubBean customBean = new CustomSubBean();
|
||||
customBean.setId(12);
|
||||
customBean.setName("aaa");
|
||||
final String s = JSONUtil.toJsonStr(customBean);
|
||||
Assert.assertEquals("12", s);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customWriteSubTest(){
|
||||
final CustomSubBean customSubBean = new CustomSubBean();
|
||||
customSubBean.setId(12);
|
||||
customSubBean.setName("aaa");
|
||||
final CustomBean customBean = new CustomBean();
|
||||
customBean.setId(1);
|
||||
customBean.setSub(customSubBean);
|
||||
|
||||
final String s = JSONUtil.toJsonStr(customBean);
|
||||
Assert.assertEquals("{\"id\":1,\"sub\":12}", s);
|
||||
|
||||
// 自定义转换
|
||||
final JSONConfig jsonConfig = JSONConfig.of();
|
||||
final Converter converter = jsonConfig.getConverter();
|
||||
jsonConfig.setConverter((targetType, value) -> {
|
||||
if(targetType == CustomSubBean.class){
|
||||
final CustomSubBean subBean = new CustomSubBean();
|
||||
subBean.setId((Integer) value);
|
||||
return subBean;
|
||||
}
|
||||
return converter.convert(targetType, value);
|
||||
});
|
||||
final CustomBean customBean1 = JSONUtil.parseObj(s, jsonConfig).toBean(CustomBean.class);
|
||||
Assert.assertEquals(12, customBean1.getSub().getId());
|
||||
}
|
||||
|
||||
@Data
|
||||
static class CustomSubBean {
|
||||
private int id;
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Data
|
||||
static class CustomBean{
|
||||
private int id;
|
||||
private CustomSubBean sub;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user