不应用GsonBuilder中的执行策略

qyzbxkaa  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(145)

我有下面的例子:

public class A implements Serializable {
    int a;
    B b;
    ...

    @Override
    public String toString() {
        Gson gson = new Gson();
        return gson.toJson(this);
    }

}
public class B implements Serializable {
    int c;
    byte[] d;
    ...

    @Override
    public String toString() {
        Gson gson = new GsonBuilder().setExclusionStrategies(new BExclusionStrategy()).create();
        return gson.toJson(this);
    }

    public class BExclusionStrategy implements ExclusionStrategy {
    @Override
    public boolean shouldSkipClass(Class<?> arg0) {
        return false;
    }

    @Override
    public boolean shouldSkipField(FieldAttributes attr) {
        return attr.getName().equals("d") && attr.getDeclaringClass() == B.class;
    }
    }
}

我想在调用类A的toString方法时排除字段d,因为字节数组非常长。但是如果我在B类中指定了执行策略,它在调用A.toString()时不适用。但是如果我把执行策略移到类A的toString方法上,它就能工作,并且字段d被省略了。
为什么会这样呢?另外,类B在多个不同的类中使用,我想省略对所有类打印d。
为什么会这样呢?另外,类B在多个不同的类中使用,我想省略对所有类打印d。
注意:我不想使用transient byte[] d,这将解决打印问题。我还在B类和excludeFieldsWithoutExposeAnnotation()类的其他字段上尝试了@ blog,但也不起作用。

wsxa1bj1

wsxa1bj11#

但是如果我在B类中指定了执行策略,它在调用A.toString()时就不适用了。但是如果我把执行策略移到类A的toString方法上,它就能工作,并且字段d被省略了。
为什么会这样呢?
因为当你调用A.toString(),它调用Gson时,它使用反射来序列化A的字段,然后是B。由于B.toString()永远不会被调用,因此您指定的排除策略没有任何效果。
我还在B类的其他字段上尝试了@ blog
Gson没有@Exclude注解,它只有@Expose@Exclude注解可能来自不同的库,但Gson会忽略它。
最简单的解决方案是使用transient字段修饰符。如果你不想这样做,那么你可以创建一个配置了自定义排除策略的Gson示例,然后所有的toString()方法都会使用这个示例。您还可以通过创建自己的@Exclude注解或类似注解并让排除策略进行检查来使排除策略更通用。
但是,由于您关心的似乎是字节数组byte[] d的长度,因此您可以在该字段上使用Gson的@JsonAdapter注解来指定一个自定义适配器,该适配器创建数组的更简洁的JSON表示。

相关问题