How to customize Jackson type information mechanism

前端 未结 2 1327
面向向阳花
面向向阳花 2021-01-05 18:14

In Jackson, I am using annotation @JsonTypeInfo to include polymorphism support.

If, I do not want to go with annotation based approach, I can use g

相关标签:
2条回答
  • 2021-01-05 18:42

    You can use Jackson's DefaultTypeResolverBuilder for this purpose. Extend this class and override the useForType method appropriately. Here is an example that adds type information only for the classes belonging to the test.jackson package (and sub-packages):

    import com.fasterxml.jackson.databind.JavaType;
    import com.fasterxml.jackson.databind.ObjectMapper.DefaultTypeResolverBuilder;
    import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
    
    public class CustomTypeResolverBuilder extends DefaultTypeResolverBuilder
    {
        public CustomTypeResolverBuilder()
        {
            super(DefaultTyping.NON_FINAL);
        }
    
        @Override
        public boolean useForType(JavaType t)
        {
            if (t.getRawClass().getName().startsWith("test.jackson")) {
                return true;
            }
    
            return false;
        }
    }
    

    Now, consider that you have Foo.java in test.jackson package and Bar.java in org.myorg package, each containing an int variable called "integer" and a String variable called "string".

    You can serialize objects of these two classes this way:

    ObjectMapper objectMapper = new ObjectMapper();
    
    TypeResolverBuilder<?> typeResolver = new CustomTypeResolverBuilder();
    typeResolver.init(JsonTypeInfo.Id.CLASS, null);
    typeResolver.inclusion(JsonTypeInfo.As.PROPERTY);
    typeResolver.typeProperty("@CLASS");
    objectMapper.setDefaultTyping(typeResolver);
    
    Foo foo = new Foo(10, "Foo");
    Bar bar = new Bar(20, "Bar");
    
    System.out.println(objectMapper.writeValueAsString(foo));
    System.out.println(objectMapper.writeValueAsString(bar));
    

    The corresponding output will be:

    {"@CLASS":"test.jackson.Foo","integer":10,"string":"Foo"}
    {"integer":20,"string":"Bar"}
    

    You can also customize the name of the attribute that represents the type ("@CLASS" in the above example). Hope this helps!

    0 讨论(0)
  • 2021-01-05 18:53

    You can use the Moonwlker library.

    With it, you can create an ObjectMapper like this:

     ObjectMapper objectMapper = new ObjectMapper();
    
     MoonwlkerModule module =
       MoonwlkerModule.builder()
         .fromProperty("@CLASS").toSubclassesOf(Animal.class)
         .build();
    
     objectMapper.registerModule(module);
    

    And then use that mapper to (de)serialize. The Moonwlker website contains more details and configuration options.

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