Java 使Gson行为依赖于深度

Java 使Gson行为依赖于深度,java,serialization,gson,Java,Serialization,Gson,有没有一种合理的方法使Gson处理嵌套对象的方式不同于顶级对象?要序列化的对象是实体,它们都有一个id。嵌套实体应替换为其id(以缩短输出并可能避免无休止的递归) 假设有一个 @AllArgsConstructor class User { int id; String name; User parent; } 我执行 User grampa = new User(3, "Grampa", null); User homer = new User(2, "Homer",

有没有一种合理的方法使Gson处理嵌套对象的方式不同于顶级对象?要序列化的对象是实体,它们都有一个
id
。嵌套实体应替换为其
id
(以缩短输出并可能避免无休止的递归)

假设有一个

@AllArgsConstructor class User {
    int id;
    String name;
    User parent;
}
我执行

User grampa = new User(3, "Grampa", null);
User homer = new User(2, "Homer", grampa);
User bart = new User(1, "Bart", homer);
序列化
bart
时得到的结果是

{
    id: 1,
    name: "Bart",
    father: {
        id: 2,
        name: "Homer",
        father: {
            id: 3,
            name: "Grampa"
        }
    }
}
这比我需要的多得多。实际上,我从来不想序列化嵌套实体,它们的
id
s已经足够好了

使用全局线程局部变量hack和
TypeAdapterFactory

{
    id: 1,
    name: "Bart",
    father: 2,
}
这正是我想要的。我更喜欢
fatherId
而不是
father
,而且我当然更喜欢一些不太粗糙的东西,而不是全局变量

我不想创建一个DAO,反射性地扫描对象,或者类似地扫描对象(那么我可以自己完成整个序列化,不是吗?)。

我认为这为“更理智”的方法指明了方向。创建一个
TypeAdapter
工厂,它封装状态并返回引用该状态的内部类
TypeAdapter
实例,如下所示:

public class UserTypeAdapterFactory {
    private Set<Integer> serializedUsers = new HashSet<>();

    public JsonSerializer<User> getTypeAdapter() {
        return (user, type, context) -> {
            JsonObject el = new JsonObject();
            el.addProperty("id", user.getId());
            el.addProperty("name", user.getName());

            if(user.getFather() != null) {
                JsonArray els = new JsonArray();
                int fatherId = user.getFather().getId();
                if(!serializedUsers.contains(fatherId)) {
                    JsonElement father = context.serialize(user.getFather());
                    if (father.isJsonArray()) {
                        els.addAll(father.getAsJsonArray());
                    } else {
                        els.add(father);
                    }
                    serializedUsers.add(fatherId);
                }
                el.addProperty("fatherId", fatherId);
                els.add(el);
                return els;
            } else {
                return el;
            }
        };
    }
}

Gson gson = new GsonBuilder()
    .registerTypeAdapter(
        User.class, 
        new UserTypeAdapterFactory().getTypeAdapter())
    .build();
System.out.println(gson.toJson(
    new User(1, "Bart", new User(2, "Homer", new User(3, "Grampa", null)))));

我很难理解这种转变。感觉很多信息都消失了。@SotiriosDelimanolis现在好多了?你想让杰克逊为格森做点什么吗?Gson扩展让你可以这样做。这很好,但它做了我想避免的事情,那就是我自己在字段上瞎混。我希望所有实体和它们的所有成员都这样,而不必枚举它们正如所写的,它不能做预期的事情,因为
serializedUsers
只得到测试和编写,而从不在其他地方使用。但是我有主意了,这是可以解决的它还使
gson
实例依赖于上下文,并迫使我在每个请求/会话中使用它,而不是将其作为单个实例使用。但让我们称之为特性,它是概念的证明。关键部分是上下文依赖。集合是一个上下文,让您知道是否需要序列化父对象。问题是序列化程序是在顶层注册的,这使得上下文是全局的。另一个选项是创建允许本地上下文的
jsonement
代理。
[{"id":3,"name":"Grampa"},{"id":2,"name":"Homer","fatherId":3},{"id":1,"name":"Bart","fatherId":2}]