2016-09-29 5 views
6

Я работаю над приложением, которое использует GSON как десериализатор json и нуждается в десериализации полиморфного json из REST API. Прежде чем объяснить, что я уже рассматривал полиморфную десериализацию с помощью GSON и успешно реализовал ее в нескольких случаях. Так что это конкретный вопрос, который у меня есть. Также я прочел this great post и this stackoverflow discussion, прежде чем задавать это. Кстати, я использую RuntimeTypeAdapterFactory для десериализации полиморфных объектов.Deserializing полиморфный JSON с исключением исключения GSON

Проблема У меня есть то, что, по-видимому, RuntimeTypeAdapterFactory GSON не позволяет объявить поле, которое указывает тип объекта внутри структуры иерархии. Далее я расскажу о некотором коде. У меня есть следующий POJOs структура (POJOs была уменьшена для простоты):

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; 
} 

В настоящее время это код, где я определил runtimeTypeAdapterFactory для иерархии пользователей.

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(); 
} 

Теперь, когда я пытаюсь десериализации JSON:

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

Я получаю это исключение

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

Но если изменить имя свойства "UserType" в моем классе BaseUser например, «типа», и я десериализую тот же самый json все правильно. Я не понимаю, почему GSON runtimTypeAdapterFactory имеет это ограничение. Фактически в this blog post, по-видимому, это не проблема.

Может ли кто-нибудь объяснить, что здесь происходит, почему имя свойства, которое определяет тип, не может быть определено внутри иерархии pojos?

EDIT Проблема не при десериализации, но при сериализации с использованием кода, описанного выше. Найдите в объяснении ответ.

+0

По ошибке, вы уверены, что не объявляли поле 'userType' в' User' класс также? Он уже объявлен в классе «BaseUser», поэтому его не нужно повторно использовать. –

+0

Привет Jyotman. Нет, я убедился, что я не декларирую полевое имя пользователя дважды. Он объявляется только базовому пользователю.Плюс я сказал в конце вопроса, десериализация работает нормально, как только измените имя поля userType из класса BaseUser на нечто иное, чем то, что объявлено на json и RuntimeTypeAdapterFactory. Но спасибо за предложение! – JorgeMuci

ответ

4

Ну, после некоторого времени копания я узнал, что проблема не является десериализацией, проблема возникает при сериализации и регистрации RuntimeTypeFactory, как описано в вопросе. Если вы регистрируете runtimeTypeAdapterFactory и использовать то же имя поля, чтобы определить тип класса на заводе и в вашем POJO, JSON в результате сериализации POJO в JSon с использованием GSON с RuntimeTypeAdapterFactory для SpecialUser, например, будет:

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

Это приведет за исключением описанного:

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

, потому что де-поле UserType повторяется в JSON из-за GSON сериализатором, который автоматически добавит поле, как заявлено в RuntimeTypeAdapterFactory зарегистрировано для класса BaseUser.

1

Я думаю, что, используя собственный UserType без @Expose аннотации будет делать трюк

Regads

Смежные вопросы