简体   繁体   中英

How to add custom deserializer to interface using jackson

Saying I have an interface A, I want to use custom deserializer for all classes implement interface A, So I use code below but it doesn't work, While CustomAserializer works. So what should I do to deserialize all classes implement A using my custom deserializer. Thanks.

module.addDeserializer(A.class, new CustomADeserializer());
module.addSerializer(A.class, new CustomASerializer())

It seems you forgot to annotate your implementation classes with @JsonDeserialize(using = ImplementationClazz.class) to indicate that the class should be used to deserialize the abstract class or interface.

The following is a simple example to deserialize an interface having multiple implementations using Jackson.

Here is my interface:

@JsonDeserialize(using = UserDeserializer.class)
public interface User {
}

One implementation of the interface:

@JsonDeserialize(as = ServiceUser.class)
public class ServiceUser implements User{

    private String name;
    private String role;

    //constructor, setters & getters

Second implementation:

@JsonDeserialize(as = AdminUser.class)
public class AdminUser implements User {

    private String role;
    private String designation;

    //constructor, setters & getters

And here is the deserializer:

public class UserDeserializer extends JsonDeserializer<User> {
    @Override
    public User deserialize(JsonParser jp, DeserializationContext context) throws IOException {
        ObjectMapper mapper = (ObjectMapper) jp.getCodec();
        ObjectNode root = mapper.readTree(jp);

        /*write your own condition*/
        if (root.has("name") && root.get("name").asText().equals("XYZ")) {
            return mapper.readValue(root.toString(), ServiceUser.class);
        }
        return mapper.readValue(root.toString(), AdminUser.class);
    }
}

You may get a StackOverflowError if you don't annotate the implementation classes. All implementation classes should deserialize themselves, otherwise it will use the deserializer from the parent class which leads to a StackOverflowError.

Just in case someone need a solution to serialize and desiralize inheritance hierarchy

you can use jackson annotation in more elegant way : JsonTypeInfo and JsonSubTypes

 @JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME, 
  include = JsonTypeInfo.As.PROPERTY, 
  property = "type")
@JsonSubTypes({ 
  @Type(value = ServiceUser.class, name = "service"), 
  @Type(value = AdminUser.class, name = "admin") 
})
public interface User{
    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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