GSON:如何在保持循环引用的同时防止StackOverflowError?

时间:2013-01-23 21:11:46

标签: java json serialization gson

我有一个带循环引用的结构。 出于调试目的,我想转储它。基本上任何格式,但我选择了JSON。

因为它可以是任何类,所以我选择了不需要JAXB注释的GSON。

但GSON会点击循环引用并递归到StackOverflowError

如何限制GSON

  • 忽略某些班级成员? <{1}}和@XmlTransient都未被遵守。

  • 忽略某些对象图路径?例如。我可以指示GSON不要序列化@JsonIgnore

  • 进入最多2个级别的深度?

相关:Gson.toJson gives StackOverFlowError, how to get proper json in this case? (public static class)

1 个答案:

答案 0 :(得分:20)

只需将字段设为瞬态(如private transient int field = 4;中所示)。 GSON理解这一点。

修改

无需内置注释; Gson允许您插入自己的策略来排除字段和类。它们不能基于路径或嵌套级别,但注释和名称都可以。

如果我想在类“my.model.Person”上跳过名为“lastName”的字段,我可以编写一个这样的排除策略:

class MyExclusionStrategy implements ExclusionStrategy {

    public boolean shouldSkipField(FieldAttributes fa) {                
        String className = fa.getDeclaringClass().getName();
        String fieldName = fa.getName();
        return 
            className.equals("my.model.Person")
                && fieldName.equals("lastName");
    }

    @Override
    public boolean shouldSkipClass(Class<?> type) {
        // never skips any class
        return false;
    }
}

我也可以制作自己的注释:

@Retention(RetentionPolicy.RUNTIME)
public @interface GsonRepellent {

}

并将shouldSkipField方法重写为:

public boolean shouldSkipField(FieldAttributes fa) {
    return fa.getAnnotation(GsonRepellent.class) != null;
}

这使我能够做以下事情:

public class Person {
    @GsonRepellent
    private String lastName = "Troscianko";

    // ...

要使用自定义ExclusionStrategy,请使用构建器构建Gson对象:

Gson g = new GsonBuilder()
       .setExclusionStrategies(new MyOwnExclusionStrategy())
       .create();