2016-08-23 6 views
1

Я использую Модернизация с Gson для десериализации. Я хочу, чтобы модифицировать ответы были интерфейсами, поэтому я сделал TypeAdapterFactory, который должен сообщать gson для десериализации Интерфейсы к их реализации класса. В моем случае FeedElement - это интерфейс, FeedElementImp - это класс, реализующий его.Gson custom TypeAdapter реализация

public class InterfaceAdapterFactory implements TypeAdapterFactory { 

@SuppressWarnings("unchecked") 
@Override 
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { 
    if (FeedElement.class.isAssignableFrom(type.getRawType())) { 
     return (TypeAdapter<T>) new FeedElementAdapter(gson); 
    } else { 
     return null; 
    } 
} 

private class FeedElementAdapter extends TypeAdapter<FeedElement> { 
    private Gson gson; 

    public FeedElementAdapter(Gson gson) { 
     this.gson = gson; 
    } 

    @Override 
    public void write(JsonWriter out, FeedElement value) throws IOException { 
     out.jsonValue(gson.toJson(value)); 
    } 

    @Override 
    public FeedElement read(JsonReader in) throws IOException { 
     return gson.fromJson(in, FeedElementImp.class); 
    } 
} 
} 

Это, конечно, не работает. Я регистрирую этот завод при создании Gson с помощью строителя. Я думаю, проблема в методах записи/чтения FeedElementAdapter.

private static ApiModule createApiModule(String baseURl, BoutAppPreferences prefs) { 
    OkHttpClient client = new OkHttpClient.Builder() 
      .addInterceptor(new RequestInterceptor(prefs)) 
      .build(); 

    Gson gson = new GsonBuilder() 
      .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") 
      .excludeFieldsWithoutExposeAnnotation() 
      .registerTypeAdapterFactory(new InterfaceAdapterFactory()) 
      .serializeNulls() 
      .create(); 

    Retrofit.Builder builder = new Retrofit.Builder() 
      .baseUrl(baseURl) 
      .client(client) 
      .addConverterFactory(GsonConverterFactory.create(gson)); 

    API api = builder.build().create(API.class); 
    return new ApiModule(api); 
} 

Вот пример вызова API.

@GET("api/feed") 
Call<List<FeedElement>> getFeedItems(); 

Как вы можете видеть, Retrofit не может десериализовать FeedItem, потому что это интерфейс. Если я ставлю Call>, то он будет работать нормально.

+0

Что такое 'десериализации"); 'часть вопроса делает –

+0

@ cricket_007 Он не был полностью стерт ненужной информации – toshkinl

+0

Как это не работает Что ошибка – peitek

ответ

0

Если у вас много объектов модели, и вы хотите удалить использование рефлексии для (де) сериализации каждого из них, вам придется написать много, много TypeAdapters.

Вы можете использовать библиотеку Stag, Stag улучшает производительность Gson, автоматически генерируя TypeAdapters без отражения для объектов вашей модели.

+0

Я не очень хочу ускорить работу Gson. Это достаточно быстро. Проблема заключается в том, что Gson или Retrofit не могут понять, что есть реализация интерфейса, который я хочу, чтобы они вернулись. реализовать адаптер, который сообщает Gson или Retrofit «InterfaceFoo de/serializes to ClassFoo». – toshkinl

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