Feature: Mix-in Annotations

(see Jira entry http://jira.codehaus.org/browse/JACKSON-76 for details)

Before version 1.2 configuring serialization could only be done using one of 2 ways:

And for third-party classes (or classes that should not have any dependency to Jackson package, including annotation definitions), only second option was available. But that means significant additional work -- wouldn't it be nice to be able to use annotations for configuration, without having to embed them within code?

Indeed! And this is exactly what "mix-in annotations are": a way to associate annotations with classes, without modifying (target) classes themselves.

That is, you can:

  1. Define that annotations of a mix-in class (or interface)

  2. will be used with a target class (or interface) such that it appears

  3. as if the target class had all annotations that the mix-in class has (for purposes of configuring serialization / deserialization)

You can think of it as kind of aspect-oriented way of adding more annotations during runtime, to augment statically defined ones.

How does it work?

You just configure ObjectMapper with associations between mix-in and target classes, to be used for serialization and deserialization.

The easiest way to do this (assuming you use Jackson 1.7 or above) is via Module interface: if you extend SimpleModule, you can do:

   1 public class MyModule extends SimpleModule
   2 {
   3   public MyModule() {
   4     super("ModuleName", new Version(0,0,1,null));
   5   }
   6   @Override
   7   public void setupModule(SetupContext context)
   8   {
   9     context.setMixInAnnotations(Target.class, MixIn.class);
  10     // and other set up, if any
  11   }
  12 }

which will register mix-ins with both serializer and deserialization configurations.

Or, if using an earlier version, you do this by:

objectMapper.getSerializationConfig().addMixInAnnotations(Target.class, MixIn.class);
objectMapper.getDeserializationConfig().addMixInAnnotations(Target.class, MixIn.class);

Example use case

Let us consider an example, where you have an existing class ("target class") Point.class, defined as:

public final class Rectangle {
    final private int w, h;
    public Rectangle(int w, int h) {
      this.w = w;
      this.h = h;
    }
    public int getW() { return w; }
    public int getH() { return h; }
    public int getSize() { return w * h; }
  }  

which would serialize, but not quite as you would want since:

or deserialize, because:

Mix-ins to the rescue!

So, here's one possible mix-in class that can be used to inject ("mix in") annotations we would want:

abstract class MixIn {
  MixIn(@JsonProperty("width") int w, @JsonProperty("height") int h) { }

  // note: could alternatively annotate fields "w" and "h" as well -- if so, would need to @JsonIgnore getters
  @JsonProperty("width") abstract int getW(); // rename property
  @JsonProperty("height") abstract int getH(); // rename property
  @JsonIgnore int getSize(); // we don't need it!
  
}

and to configure our ObjectMapper we'd use:

objectMapper.getSerializationConfig().addMixInAnnotations(Rectangle.class, MixIn.class);
objectMapper.getDeserializationConfig().addMixInAnnotations(Rectangle.class, MixIn.class);

Usage notes

Here are some notes on what kinds of annotations can be used, and for what purpose:

External Documentation

Here is some related documentation:


CategoryJackson

JacksonMixInAnnotations (last edited 2012-02-29 16:13:04 by TatuSaloranta)

Copyright ©2009 FasterXML, LLC