修复JSON反序列化时,引用字段类型的自定义JsonDeserializer无效

This commit is contained in:
Looly
2022-09-04 23:18:42 +08:00
parent 508c139b22
commit 11724c8761
7 changed files with 116 additions and 6 deletions

View File

@@ -0,0 +1,43 @@
package cn.hutool.json;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.impl.BeanConverter;
import cn.hutool.json.serialize.GlobalSerializeMapping;
import cn.hutool.json.serialize.JSONDeserializer;
import java.lang.reflect.Type;
/**
* 针对JSON的Bean转换封装。<br>
* 此类时针对5.x中设计缺陷设计的类在ConverterRegistry中通过反射调用
*
* @param <T> Bean类型
* @since 5.8.6
*/
public class BeanConverterForJSON<T> extends BeanConverter<T> {
public BeanConverterForJSON(Type beanType) {
super(beanType);
}
@Override
protected T convertInternal(final Object value) {
final Class<T> targetType = getTargetType();
if (value instanceof JSON) {
final JSONDeserializer<?> deserializer = GlobalSerializeMapping.getDeserializer(targetType);
if (null != deserializer) {
//noinspection unchecked
return (T) deserializer.deserialize((JSON) value);
}
// issue#2212@Github
// 在JSONObject转Bean时读取JSONObject本身的配置文件
if (value instanceof JSONGetter && BeanUtil.hasSetter(targetType)) {
final JSONConfig config = ((JSONGetter<?>) value).getConfig();
this.copyOptions.setIgnoreError(config.isIgnoreError());
}
}
return super.convertInternal(value);
}
}

View File

@@ -28,7 +28,7 @@ public class JSONConverter implements Converter<JSON> {
static {
// 注册到转换中心
ConverterRegistry registry = ConverterRegistry.getInstance();
final ConverterRegistry registry = ConverterRegistry.getInstance();
registry.putCustom(JSON.class, JSONConverter.class);
registry.putCustom(JSONObject.class, JSONConverter.class);
registry.putCustom(JSONArray.class, JSONConverter.class);

View File

@@ -768,11 +768,16 @@ public class JSONUtil {
if (null != serializer) {
final Type jsonType = TypeUtil.getTypeArgument(serializer.getClass());
if (null != jsonType) {
final JSON json;
if (serializer instanceof JSONObjectSerializer) {
serializer.serialize(new JSONObject(jsonConfig), object);
json = new JSONObject(jsonConfig);
} else if (serializer instanceof JSONArraySerializer) {
serializer.serialize(new JSONArray(jsonConfig), object);
json = new JSONArray(jsonConfig);
} else{
throw new JSONException("Unsupported JSONSerializer type: " + serializer.getClass());
}
serializer.serialize(json, object);
return json;
}
}
@@ -810,7 +815,7 @@ public class JSONUtil {
// 默认按照JSONObject对待
return new JSONObject(object, jsonConfig);
} catch (Exception exception) {
} catch (final Exception exception) {
return null;
}
}

View File

@@ -0,0 +1,54 @@
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.json.serialize.JSONDeserializer;
import cn.hutool.json.serialize.JSONObjectSerializer;
import lombok.Data;
import org.junit.Assert;
import org.junit.Test;
public class Issue2555Test {
@Test
public void serAndDeserTest(){
JSONUtil.putSerializer(MyType.class, new MySerializer());
JSONUtil.putDeserializer(MyType.class, new MyDeserializer());
final SimpleObj simpleObj = new SimpleObj();
final MyType child = new MyType();
child.setAddress("addrValue1");
simpleObj.setMyType(child);
final String json = JSONUtil.toJsonStr(simpleObj);
Assert.assertEquals("{\"myType\":{\"addr\":\"addrValue1\"}}", json);
//MyDeserializer不会被调用
final SimpleObj simpleObj2 = JSONUtil.toBean(json, SimpleObj.class);
Assert.assertEquals("addrValue1", simpleObj2.getMyType().getAddress());
}
@Data
public static class MyType {
private String address;
}
@Data
public static class SimpleObj {
private MyType myType;
}
public static class MySerializer implements JSONObjectSerializer<MyType> {
@Override
public void serialize(JSONObject json, MyType bean) {
json.set("addr", bean.getAddress());
}
}
public static class MyDeserializer implements JSONDeserializer<MyType>{
@Override
public MyType deserialize(JSON json) {
final MyType myType = new MyType();
myType.setAddress(((JSONObject)json).getStr("addr"));
return myType;
}
}
}