2016-09-29 21 views
6

Pracuję nad app, który używa GSON jako json Deserializatora i musi deserializowania polimorficzny json z REST API. Zanim wyjaśniam mi, proszę zauważyć, że już szukałem polimorficznej deserializacji z GSONem i wdrożyłem ją w kilku przypadkach z powodzeniem. To jest specyficzny problem, który mam. Przeczytałem też this great post i this stackoverflow discussion zanim się o to zapytam. Używam RuntimeTypeAdapterFactory do deserializacji obiektów polimorficznych przy okazji.deserializacji polimorficzny JSON z GSON rzuca wyjątek

Problem polega na tym, że GSON RuntimeTypeAdapterFactory nie pozwala zadeklarować pola, które określa typ obiektu wewnątrz struktury hierarchii. Wyjaśnię dalej za pomocą kodu. Mam następującą strukturę POJOs (POJOs została zredukowana do uproszczenia):

public abstract class BaseUser { 
    @Expose 
    protected EnumMobileUserType userType; 
} 


public class User extends BaseUser { 
    @Expose 
    private String name; 
    @Expose 
    private String email;  
} 

public class RegularUser extends User { 
    @Expose 
    private String address;  
} 

public class SpecialUser extends User { 
    @Expose 
    private String promoCode; 
} 

Teraz jest to kod gdzie zdefiniował runtimeTypeAdapterFactory dla hierarchii Użytkownika.

public static RuntimeTypeAdapterFactory<BaseUser> getUserTypeAdapter() { 
    return RuntimeTypeAdapterFactory 
     .of(BaseUser.class, "userType") 
     .registerSubtype(User.class, EnumMobileUserType.USER.toString()) 
     .registerSubtype(RegularUser.class, EnumMobileUserType.REGULAR.toString()) 
     .registerSubtype(SpecialUser.class, EnumMobileUserType.SPECIAL.toString()); 
} 

public static Gson getGsonWithTypeAdapters() { 
    GsonBuilder builder = new GsonBuilder(); 
    builder.registerTypeAdapterFactory(getUserTypeAdapter()); 
    return builder.create(); 
} 

Teraz, gdy próbuję deserializować JSON:

{ 
    "user":{ 
     "userType":"USER", 
     "email":"[email protected]", 
     "name":"Albert" 
    } 
} 

otrzymuję ten wyjątek

com.google.gson.JsonParseException: cannot serialize com.mobile.model.entities.v2.common.User because it already defines a field named userType 

Ale jeśli zmienić nazwę właściwości "UserType" w mojej klasie BaseUser na przykład "typ" i deserializuję to samo poprawnie. Nie rozumiem, dlaczego GSON runtimTypeAdapterFactory ma to ograniczenie. W rzeczywistości w this blog post najwyraźniej nie jest to problemem.

Może ktoś wyjaśnić, co tu się dzieje, dlaczego nazwa obiektu, który określa typ nie może być zdefiniowana wewnątrz hierarchii POJOs?

EDYCJA Problem nie występuje podczas deserializacji, ale w przypadku serializacji za pomocą kodu opisanego powyżej. Znajdź dodatkowe wyjaśnienie w odpowiedzi.

+0

Zgodnie z błędu, to na pewno nie zadeklarowały pole 'userType' w' użytkownik portu klasa też? Jest już zadeklarowany w klasie "BaseUser", więc nie trzeba go redeclare. –

+0

Witaj Jyotman. Nie, upewniłem się, że nie zadeklarowałem dwa razy wartości usertype pola. Jest zadeklarowany tylko dla użytkownika podstawowego.Plus powiedziałem na końcu pytania, deserializacja działa dobrze, gdy tylko zmieni nazwę pola userType z klasy BaseUser na coś innego niż to, co jest zadeklarowane w json i RuntimeTypeAdapterFactory. Ale dzięki za sugestię! – JorgeMuci

Odpowiedz

4

Cóż, po wykopaniu jakimś czasie okazało się, że problem nie jest faktycznie deserializacji, problem pojawia się, gdy szeregowania i posiadające RuntimeTypeFactory zarejestrowaną w sposób opisany w pytaniu. Jeśli zarejestrujesz się runtimeTypeAdapterFactory i używać tej samej nazwy pola, aby określić typ klasy w fabryce iw swoim POJO, json wynikającej z szeregowania POJO do JSON przy użyciu GSON z RuntimeTypeAdapterFactory dla SpecialUser na przykład będą:

{ 
    "user":{ 
     "userType":"SPECIAL", 
     "email":"[email protected]", 
     "name":"Albert" 
     "userType":"SPECIAL" 
    } 
} 

To spowoduje wyjątkiem opisanym:

com.google.gson.JsonParseException: cannot serialize com.mobile.model.entities.v2.common.User because it already defines a field named userType 

ponieważ de pole UserType jest powtarzany w json powodu GSON serializatora, który będzie automatycznie dodać pole deklarowanego w RuntimeTypeAdapterFactory zarejestrowanym dla BaseUser klasy.

1

myślę, że za pomocą własnego UserType bez @Expose adnotacji rade

Regads

Powiązane problemy