目前正在使用GSON进行反序列化并使用改造GsonConverterFactory进行改造:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(new TypeToken<Map<Book, Collection<Author>>>(){}.getType(), new BooksDeserializer(context));
Gson gson = gsonBuilder.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
BookService service = retrofit.create(BookService.class);
Response<Map<Book, Collection<Author>>> response = service.getBooks().execute();
我想使用改装提供的JacksonConverterFactory?我需要提供杰克逊映射器。有没有办法像我使用GSON一样向该映射器提供类型信息?
SimpleModule simpleModule = new SimpleModule();
// TODO provide mapper with info needed to deserialize
// Map<Book, Collection<Author>>
mapper.registerModule(simpleModule);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(JacksonConverterFactory.create(mapper))
.build();
BookService service = retrofit.create(BookService.class);
Response<Map<Book, Collection<Author>>> response = service.getBooks().execute();
专门研究TODO,我可以告诉映射器使用这个反序列化器吗?
public class BooksDeserializer extends JsonDeserializer<Map<Book, Collection<Author>>> {
@Override
public Map<Book, Collection<Author>> deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
// deserialize here
}
}
答案 0 :(得分:3)
根据API,SimpleModule.addDeserializer(java.lang.Class, com.fasterxml.jackson.databind.JsonSerializer)
requires an instance of JsonSerializer<T>
whereby T is a supertype of the class you supply as an argument,即反序列化器需要能够反序列化作为所提供类的子类的对象; TypeReference<Map<Book, Collection<Author>>>
不是Map<Book, Collection<Author>>
的子类型。
然而,由于Java的类型擦除,为地图编写序列化器并不容易。一种方法是为地图编写一个包装类,例如
@XmlRootElement
public class SerializableBookMapWrapper {
private Map<Book, Collection<Author>> wrapped;
public SerializableBookMapWrapper(final Map<Book, Collection<Author>> wrapped) {
this.wrapped = wrapped;
}
public Map<Book, Collection<Author>> getWrapped() {
return wrapped;
}
public void setWrapped(final Map<Book, Collection<Author>> wrapped) {
this.wrapped = wrapped;
}
}
使用这种包装类,您可以实现JsonDeserializer<SerializableBookMapWrapper>
并使用它。但是,如果您未在Book
和Author
的定义中使用Jackson annotations,则还需要提供custom deserializers for them。
或者,您也可以尝试supplying this type information while actually using the ObjectMapper
instance for deserialization。
答案 1 :(得分:0)
我认为这里存在误解:你没有实现JsonDeserializer
只是因为你想要绑定到某种类型。这就是杰克逊本身所做的。
如果由于某种原因需要定制的反序列化器(或序列化器),它只会处理嵌套类型的特定部分; Book
或Author
或Map
的反序列化程序,但对于嵌套类型Map
,反序列化程序委托给键和值处理程序。它没有注册组合。
无论如何:我相当确定自定义反序列化器不是这里的答案,而是一种将ObjectMapper
的基本用法包装为读取给定类型的JSON的方法。但是,如果不了解更多有关Retrofit的信息,我不知道究竟是什么。