fastjson2 icon indicating copy to clipboard operation
fastjson2 copied to clipboard

[BUG]ValueFilter过滤对于json字符串发现没有进入apply方法,没法生效

Open Vetich opened this issue 5 months ago • 7 comments

问题描述

简要描述您碰到的问题。 ValueFilter过滤对于json字符串发现没有进入apply方法,没法生效

环境信息

请填写以下信息:

  • OS信息: [e.g.:CentOS 8.4.2105 4Core 3.10GHz 16 GB]
  • JDK信息: [e.g.:Openjdk 1.8.0_312]
  • 版本信息:[e.g.:Fastjson2 2.x.x]

重现步骤

如何操作可以重现该问题:

类似代码如下

     String str =
            "{\"num\":\"18005509635\",\"fee\":\"2000\"}";
     JSON.toJSONString(str, new Filter())

     public class Filter implements ValueFilter {
	@Override
    public Object apply(Object object, String name, Object value) {
        return ["num"].containsKey(name.toUpperCase(Locale.ENGLISH)) ? "****" : value;
    }
}

期待的正确结果

对您期望发生的结果进行清晰简洁的描述。 "{"num":"****","fee":"2000"}"

但是实际上还是输出原有的值"{"num":"18005509635","fee":"2000"}" 有点奇怪

我需要将 JSON.toJSONString(JSON.parseObject(str), new Filter()) 才可以输出期待结果

相关日志输出

请复制并粘贴任何相关的日志输出。

附加信息

如果你还有其他需要提供的信息,可以在这里填写(可以提供截图、视频等)。

Vetich avatar Jul 26 '25 09:07 Vetich

是要表达这个意思吗?

    @Test
    public void test() {
        TestData testData = new TestData("18005509635", "2000");
        JSON.toJSONString(testData, new Filter());
    }
    
    @Data
    @AllArgsConstructor
    public static class TestData {
        private String num;
        private String free;
    }
    
    public class Filter implements ValueFilter {
        @Override
        public Object apply(Object object, String name, Object value) {
            ……
        }
    }

jujn avatar Jul 27 '25 02:07 jujn

  @Test
    public void test() {
        String str = "{\"num\":\"18005509635\",\"fee\":\"2000\"}";
        JSONObject jsonObject = JSON.parseObject(str);
        String result = JSON.toJSONString(jsonObject, new Filter());
        assertEquals("{\"num\":\"****\",\"fee\":\"2000\"}", result);
    }

    public class Filter implements ValueFilter {
        @Override
        public Object apply(Object object, String name, Object value) {
            return Collections.singleton("num").contains(name.toLowerCase(Locale.ENGLISH)) ? "****" : value;
        }
    }

测试过,ValueFilter可以起作用的啊

wenshao avatar Jul 27 '25 09:07 wenshao

@wenshao 其实我直接JSON.toJSONString(str, new Filter()) 这种情况不行 如果JSON.paraseObject是可以的 因为我的场景是一个大串的JSON字符串 字符串又存在子对象的形式 只做一层paraseObject 还是没法进行第二层字对象的匿名化

Vetich avatar Jul 28 '25 01:07 Vetich

@wenshao 其实我直接JSON.toJSONString(str, new Filter()) 这种情况不行 如果JSON.paraseObject是可以的 因为我的场景是一个大串的JSON字符串 字符串又存在子对象的形式 只做一层paraseObject 还是没法进行第二层字对象的匿名化

可以JSON.toJSONString(JSON.parseObject(str, str对应的原始javabean.class), new Filter()),如果直接JSON.parseObject(str),框架无法得知字符串的原始类型

jujn avatar Jul 28 '25 02:07 jujn

@jujn 这种应该也点难搞 因为基于切面的实现 所有的bean都抽象成object 没法指定对应的bean类型来着

Vetich avatar Jul 28 '25 03:07 Vetich

@Vetich 您可以发一下json结构,也许有其他方式实现您的效果。因为您提供的例子,ValueFilter是起作用的

 @Test
    public void test() {
        String str = "{\"num\":\"18005509635\",\"fee\":\"2000\",\"children\":[{\"num\":\"12\",\"fee\":\"1\"}]}";
        JSONObject jsonObject = JSON.parseObject(str);
        String result = JSON.toJSONString(jsonObject, new Filter());
        assertEquals("{\"num\":\"****\",\"fee\":\"2000\",\"children\":[{\"num\":\"****\",\"fee\":\"1\"}]}", result);
    }

    public class Filter implements ValueFilter {
        @Override
        public Object apply(Object object, String name, Object value) {
            return Collections.singleton("num").contains(name.toLowerCase(Locale.ENGLISH)) ? "****" : value;
        }
    }

mymde avatar Jul 30 '25 03:07 mymde

我也遇到一样的需求,我查看了源代码,发现从对象转换为json字符串,可以使用 ValueFilter并生效,但是如果是json 字符串转换为 Java 对象,不支持 ValueFilter。在源码中我发现 readFilter 并没有支持 ValueFilter。JSONReader 如下源码所示,只处理了 AutoTypeBeforeHandler 和 ExtraProcessor,但是 JSONWriter 中处理了 ValueFilter 。

我跟踪了源码,发现 json 字符转换为 Object,使用了 DynamicClassLoader,这块比较复杂,想改源代码也不知道从何下手。

官方能否增加对 Reader 支持 ValueFilter ?功能同 Writer,让开发者可以根据自己的需求处理 jsonField -> objectField。

xzxiaoshan avatar Nov 08 '25 06:11 xzxiaoshan