How to add custom deserializer to interface using jackson

后端 未结 2 1809
挽巷
挽巷 2021-01-02 07:42

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 wo

相关标签:
2条回答
  • 2021-01-02 08:08

    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{
        // ...
    }
    
    0 讨论(0)
  • 2021-01-02 08:19

    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.

    0 讨论(0)
提交回复
热议问题