Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson - Custom TypeId Resolver

Tags:

java

jackson

I've been using a custom typeId resolver for one of my classes, so far I've been leaning on the annotation support:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.CUSTOM,
    include = JsonTypeInfo.As.PROPERTY,
    property = "@type")
@JsonTypeIdResolver(ColumnDefinitionTypeResolver.class)

But now I need to customize the creation of the type resolver by passing some other dependencies to it via constructor or setters, and since Jackson is the one who instantiate it I can't find a way around it.

Is there a way to configure the ObjectMapper to use a TypeIdResolver instead of relying on annotations?

Regards

like image 780
Vinicius Carvalho Avatar asked Jan 15 '16 15:01

Vinicius Carvalho


People also ask

What is JsonPOJOBuilder?

6. @JsonPOJOBuilder. The @JsonPOJOBuilder annotation is used to configure a builder class to customize deserialization of a JSON document to recover POJOs when the naming convention is different from the default.

What is JsonIdentityInfo?

The @JsonIdentityInfo annotation is used when an object has a parent-child relationship in the Jackson library. The @JsonIdentityInfo annotation is used to indicate the object identity during the serialization and deserialization process.

What is @JsonTypeInfo?

@JsonTypeInfo is used to indicate details of type information which is to be included in serialization and de-serialization.


2 Answers

So you have two options:

1) If you're set on using the @JsonTypeIdResolver your stuck using static state in your TypeIdResolver. This probably isn't what you want.

The default JacksonAnnotationIntrospector will try to create an instance of the type you provide using JsonTypeIdResolver per its default constructor. There is currently no way to configure it to do otherwise.

public final class ColumnDefinitionTypeResolver implements TypeIdResolver {
  // You could rely on static state.
  public static String SOME_ACCESSIBLE_OBJECT = null;

  public ColumnDefinitionTypeResolver() {
    // This is what gets called.
  }
}

ColumnDefinitionTypeResolver.SOME_ACCESSIBLE_OBJECT = "I can affect the implementation from here, but using static state ... be careful";

2) Is create a module to handle deserialization of your type and subtypes.

SimpleModule columnDefinitionModule = new SimpleModule("colDefMod", new Version(1, 0, 0, null))
      .addDeserializer(ColumnDefinition.class, new JsonDeserializer() {
           @Override
           public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,  JsonProcessingException {
                // Need to read the type out and then use ObjectMapper to deserialize using the correct token
            }
        })
        .registerSubtypes(...); // add your subtypes here.

(new ObjectMapper()).registerModule(columnDefinitionModule);

For more detailed examples, see Jackson documentation How-To: Custom Deserializers.

like image 124
vpiTriumph Avatar answered Oct 04 '22 20:10

vpiTriumph


You can also set a custom type id resolver programmatically. Look at the top answer here. Look for this line:

typeResolver.init(JsonTypeInfo.Id.CLASS, null);

Replace null with your type id resolver.

like image 43
bertilmuth Avatar answered Oct 04 '22 22:10

bertilmuth