[英]Trying to migrate custom generic gson deserializer to jackson
Currently deserializing with GSON and retrofit using retrofits GsonConverterFactory: 目前正在使用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();
I would like to use the JacksonConverterFactory that is provided by retrofit? 我想使用改造提供的JacksonConverterFactory? I would need to provide that a Jackson mapper. 我需要提供杰克逊映射器。 Is there a way to provide the type information to that mapper like I did with GSON? 有没有办法像我使用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();
Looking specifically at the TODO can I tell the mapper to use this deserializer? 具体看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
}
}
According to the 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 , ie the deserializer needs to be able to deserialize objects which are a subclass of the supplied class; 根据API , SimpleModule.addDeserializer(java.lang.Class, com.fasterxml.jackson.databind.JsonSerializer)
需要一个JsonSerializer<T>
的实例,其中T是您作为参数提供的类的超类型 ,即解串器需要能够反序列化作为提供的类的子类的对象; TypeReference<Map<Book, Collection<Author>>>
is not a subtype of Map<Book, Collection<Author>>
. TypeReference<Map<Book, Collection<Author>>>
不是 Map<Book, Collection<Author>>
的子类型。
However, writing a serializer for maps is not easy thanks to Java's type erasure. 但是,由于Java的类型擦除,为地图编写序列化器并不容易。 One way of doing this is to write a wrapper class for your map, such as 一种方法是为地图编写一个包装类,例如
@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;
}
}
With this kind of wrapper class, you can implement a JsonDeserializer<SerializableBookMapWrapper>
and use that instead. 使用这种包装类,您可以实现JsonDeserializer<SerializableBookMapWrapper>
并使用它。 However, if you haven't used Jackson annotations in the definition of Book
and Author
, you need to supply custom deserializers for them as well. 但是,如果您没有在Book
and Author
的定义中使用Jackson注释 ,则还需要为它们提供自定义反序列化器 。
Alternatively, you can also try supplying this type information while actually using the ObjectMapper
instance for deserialization . 或者,您也可以尝试提供此类型信息,同时实际使用ObjectMapper
实例进行反序列化 。
I think there is misunderstanding here: you do NOT implement JsonDeserializer
just because you want to bind into some type. 我认为这里存在误解:你没有实现JsonDeserializer
只是因为你想绑定到某种类型。 This is what Jackson itself does. 这就是杰克逊本身所做的。 And if you need for some reason customized deserializer (or serializer), it will only handle specific part of nested type; 如果由于某种原因需要定制的反序列化器(或序列化器),它只会处理嵌套类型的特定部分; deserializer for Book
or Author
or Map
, but for nested types Map
deserializer delegates to key and value handlers. 用于Book
或Author
或Map
反序列化器,但用于嵌套类型Map
deserializer委托给键和值处理程序。 It does NOT register itself for combination. 它没有注册组合。
Anyway: I am fairly certain that custom deserializer is not the answer here, but a way to wrap basic usage of ObjectMapper
to read JSON as given type. 无论如何:我相当确定自定义反序列化器不是这里的答案,而是一种将ObjectMapper
基本用法包装为读取给定类型的JSON的方法。 But without knowing more about Retrofit I don't know what exactly. 但是,如果不了解更多关于Retrofit的信息,我不知道究竟是什么。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.