[FEATURE] Read时 ValueFilters 不起作用。源码发现 Read 暂不支持 ValueFilter,作者能否增强对Read 支持 ValueFilter,搜了issue,很多人都有统一的的需求。
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); config.setReaderFilters(new FieldCodecDecodeValueFilter());
public class FieldCodecDecodeValueFilter implements ExtraProcessor {
@Override
public void processExtra(Object object, String key, Object value) {
System.out.println("test");
}
}
http post 数据到 Controller 中,参数是Java对象,设置了 ReaderFilters ,processExtra 不起任何作用,完全没有被执行。
converter 都执行了,debug parseObject 也执行了。只是单纯的 Filter 完全不执行。
我本地测试2.0.60版本没有问题,你是用的最新版本吗?另外,可以提供下控制器方法、请求参数吗,方便诊断问题
@jujn 抱歉,我理解错误这个类的作用了。它仅仅能处理java对象包含的属性之外多余的 key。(经过测试,多余的json key 是可以执行的,符合这个类的定义),我临时关闭了这个 issue。
但是,实际上我是想自定义处理所有key,我的实际需求是要对使用了自定义解密注解的java对象字段进行解密,请教一下我应该使用哪个接口或者如何设置来实现我的需求?谢谢。json -> 对象。
这样可以吗?
public class CustomObjectReader<T> implements ObjectReader<T> {
private final ObjectReader<T> defaultReader;
public CustomObjectReader(ObjectReader<T> defaultReader) {
this.defaultReader = defaultReader;
}
@Override
public T readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
T object = defaultReader.readObject(jsonReader, fieldType, fieldName, features);
if (object != null) {
for (Field field : object.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(Decrypt.class)) {
field.setAccessible(true);
try {
Object value = field.get(object);
if (value instanceof String) {
field.set(object, new StringBuilder((String) value).reverse().toString());
}
} catch (IllegalAccessException ignored) {
}
}
}
}
return object;
}
}
@Test
public void test() {
ObjectReader<User> defaultUserReader = JSONFactory.getDefaultObjectReaderProvider().getObjectReader(User.class);
CustomObjectReader<User> customUserReader = new CustomObjectReader<>(defaultUserReader);
JSON.register(User.class, customUserReader);
String json = "{\"name\":\"John\",\"sensitiveData\":\"atad\"}";
User user = JSON.parseObject(json, User.class);
System.out.println(user.getSensitiveData());
}
@jujn 是一种方法,但是也存在一些问题。这样必须保证T 这个object 需要处理的字段是String类型,如果 json 报文中是字符串密文,解密后应该是一个long类型,readObject 就因为对象类型不一致就会报错了。 需要在字段读取时处理,然后解密后变成真实的值这样赋值给 T 对象的Field 才可以。
我简单看了下 是不是得从 FieldReader 下手?
目前遇到这个问题是反序列化(即json reader的过程),对于 Writer(序列化)来说,就非常简单,下面是我的代码,只是为什么 Reader 就没有直接提供 Writer 这种机制的 ValueFilter。
FastJsonConfig config = new FastJsonConfig();
config.setWriterFilters(new FieldCodecEncodeValueFilter());
public class FieldCodecEncodeValueFilter implements ValueFilter {
@Override
public Object apply(Object object, String name, Object value) {
if (value == null) {
return null;
}
// 判断字段上的注解
Field field = findField(object.getClass(), name);
if (field != null && field.isAnnotationPresent(FieldCodec.class)) {
// 执行加密
return FieldCodecUtils.encode(value.toString());
}
return value;
}
/**
* 递归查找字段(包括父类)
*/
protected Field findField(Class<?> clazz, String fieldName) {
while (clazz != null && clazz != Object.class) {
try {
return clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
return null;
}
}
@jujn 看来有很多人都需要同样的功能,不知道作者能否增强对 read 支持 valueFilter
@wenshao 能否重点支持一下这个功能,应该有很多人都需要。
@xzxiaoshan 我最近抽时间去研究一下吧,如果你有好的见解,也欢迎提交 pr
@jujn 现在的 read 实现,处理这个问题,有点棘手。我发现 json 转对象时,时拿对象Field 目标类型来分别对应不同的FieldReader 类,通过 readFieldValue 方法来返回结果的。 如下 FieldReaderBoolField 类所示:
public Object readFieldValue(JSONReader jsonReader) {
return jsonReader.readBool();
}
因为对象字段的类型已经锁定了具体的处理类,比如我的目标字段是 boolean,但是我的实际 json 可能是 “是|否” ,此时使用 jsonReader.readBool() 肯定不行的。
如果read的处理方式不是按目标对象字段类型,而是先通过 jsonReader 读取json的原始值再按照目标类型字段进行一个转换。这样的话,就可以很方便的读取原始json值后增加一个 ValueFilter 的调用,然后再进行后置处理。
@jujn 有实时通讯工具方便联系吗?比如微信、qq之类的,我现在项目需要这个功能,我想帮着修改源代码PR,但是怕修改不合适需要一些基本的指导。如果方便添加,可以将添加方式发送至 [email protected]
@jujn 有实时通讯工具方便联系吗?比如微信、qq之类的,我现在项目需要这个功能,我想帮着修改源代码PR,但是怕修改不合适需要一些基本的指导。如果方便添加,可以将添加方式发送至 [email protected]
您可以直接提交 pr,会有代码 review 的环节。
我现在在本地把 FidldReader 的各种类型的子类都修改了,埋了扩展接口的调用,但是我发现完全没有生效,不知道为什么,不知道是不是跟 DynamicClassLoader 有关系。
目前修改思路,主要是在所有 field set 赋值之前调用扩展口。
暴露的接口是下面定义:
public interface ReadObjectFieldValueFilter extends Filter {
/**
* Reads and processes a field value from the JSON reader.
*
* @param jsonReader The JSON reader containing the field data
* @param field The field being processed
* @return The processed field value, or null if no custom processing is needed
*/
Object readFieldValue(JSONReader jsonReader, Field field);
}
@jujn 关于没生效,可能没有找准切入点,有什么思路提供一下吗?
@wenshao 想跟您请教下,在反序列化时引入 valueFilter 是否可行?我担心还会引起类似 AutoType 的问题