简体   繁体   English

尝试将自定义通用gson反序列化器迁移到jackson

[英]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; 根据APISimpleModule.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. 用于BookAuthorMap反序列化器,但用于嵌套类型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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM