2015-10-10 16 views
3

有沒有讓Gson處理嵌套對象與頂層不同的一種理智方法?要序列化的東西是實體,它們都有一個id。一個嵌套的實體應該被它的id取代(以縮短輸出並可能對抗無盡的遞歸)。使Gson的行爲具有深度依賴性

比方說,有一個

@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就足夠好了。

使用 全球 線程局部變量的黑客和TypeAdapterFactory我可以得到

{ 
    id: 1, 
    name: "Bart", 
    father: 2, 
} 

這是我想要什麼差不多。我更喜歡fatherIdfather,我肯定更喜歡比全局變量更簡單的東西。

我不想創建DAO,反射或類似地掃描對象(然後我可以自己完成整個序列化,不是嗎?)。

+0

我有一個很難理解的轉變。感覺好像很多信息都消失了。 –

+0

@SotiriosDelimanolis現在好多了? – maaartinus

+0

你想爲傑森的[對象標識](http://wiki.fasterxml.com/JacksonFeatureObjectIdentity)爲Gson嗎? Gson擴展[GraphAdapterBuilder](http://stackoverflow.com/q/10036958/880772)讓你有點這樣做。 – approxiblue

回答

1

Gson documentation我認爲這是一種「更加健全」的方法。創建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))))); 

這應該打印:

[{"id":3,"name":"Grampa"},{"id":2,"name":"Homer","fatherId":3},{"id":1,"name":"Bart","fatherId":2}] 
+0

這很好,但它做我想避免的,即與我自己的領域鬼混。我希望所有實體及其所有成員都沒有列舉它們。 +++正如所寫的,它不能做預期的事情,因爲'serializedUsers'只能被測試和寫入,但從未使用過。但我已經明白了,這可以修復。 +++它也使'gson'實例上下文相關並迫使我按請求/會話使用它,而不是作爲單例使用。但是,我們稱之爲功能。 – maaartinus

+0

這是一個概念證明。關鍵部分是上下文依賴。該集是一個上下文,可讓您知道是否需要序列化父親。問題在於,序列化程序是在頂層註冊的,這使得上下文是全局的。另一種選擇是創建一個允許本地上下文的'JsonElement'代理。 – sh0rug0ru