1

We use jackson throughout our application to serialize and deserialize Java objects to JSON. It works great.

Is it possible, perhaps through a custom serializer, to serialize only properties of a Java object that are Annotated with a custom annotation?

So, given the custom annotation:

public @interface SpecialField {}

And the following bean

public SomeBean {
   @SpecialField
   private Object propertyIncluded;

   private Object propertyExcluded;
}

What would a custom serializer (or some equivalent mechanism) look like to serialize propertyIncluded (using the normal jackson object mapper) and ignore propertyExcluded?

We can't use standard jackson annotations (@JsonIgnore) in this use case because it would break our other serialization uses cases in the application.

alba lion
  • 93
  • 6
  • You can make jackson comply with the transient keyword, or use @JsonIgnore check this out: http://stackoverflow.com/questions/21745593/why-jackson-is-serializing-transient-member-also – Mark W Oct 02 '14 at 23:07
  • It seems like your answer might be over here http://stackoverflow.com/questions/7105745/how-to-specify-jackson-to-only-use-fields-preferably-globally – user3784915 Oct 02 '14 at 23:20
  • We can't use @JsonIgnore for this use case as it would break our other uses of Jackson that serialize these objects. – alba lion Oct 02 '14 at 23:26
  • so you only want to make them transient in one instance, and serialize those fields in others? – Mark W Oct 02 '14 at 23:28
  • @MarkW, in this particular instance, we'd like to serialize just fields that are annotated with a given annotation. We don't want to use `@Transient` or `@JsonIgnore` because they are already used and have meaning (as they should) for normal serialization elsewhere. – alba lion Oct 02 '14 at 23:38
  • @albalion Im talking about the transient keyword, maybe my answer below will be useful. – Mark W Oct 02 '14 at 23:58

1 Answers1

0

While this might not be quite what your looking for, It is possible to make the jackson engine serialize objects differently via some tweaking. In my example below I create two types of serializers which will or wont serialize a field marked as transient.

import java.io.Serializable;

import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.map.ObjectMapper;

public class Test {

    public static void main(String[] args) throws Exception {
        ISerializer d = new Doesnt();
        ISerializer o = new Observes();

        SomeObject obj = new SomeObject();

        System.out.println("Doesnt: " + d.serialize(obj));

        System.out.println("Observes: " + o.serialize(obj));
    }
    public static class Doesnt implements ISerializer<SomeObject> {

        @Override
        public String serialize(SomeObject o) throws Exception {
            ObjectMapper om = new ObjectMapper();
            om.setVisibilityChecker(
                    om.getSerializationConfig().
                    getDefaultVisibilityChecker().
                    withFieldVisibility(JsonAutoDetect.Visibility.ANY).
                    withGetterVisibility(JsonAutoDetect.Visibility.ANY));
            return om.writeValueAsString(o);
        }

    }

    public static class Observes implements ISerializer<SomeObject> {

        @Override
        public String serialize(SomeObject o) throws Exception {
            ObjectMapper om = new ObjectMapper();
            om.setVisibilityChecker(
                    om.getSerializationConfig().
                    getDefaultVisibilityChecker().
                    withFieldVisibility(JsonAutoDetect.Visibility.ANY).
                    withGetterVisibility(JsonAutoDetect.Visibility.NONE));
            return om.writeValueAsString(o);
        }       
    }
    public interface ISerializer<T> {
        public String serialize(T o) throws Exception;
    }

    public static class SomeObject implements Serializable {
        private static final long serialVersionUID = 745063791749142843L;
        private transient String myVar = "Transient";
        private String myOther = "Not Transient";
        public String getMyVar() {
            return myVar;
        }
        public void setMyVar(String myVar) {
            this.myVar = myVar;
        }
        public String getMyOther() {
            return myOther;
        }
        public void setMyOther(String myOther) {
            this.myOther = myOther;
        }
    }
}

output:

Doesnt: {"myVar":"Transient","myOther":"Not Transient"}
Observes: {"myOther":"Not Transient"}

I would think it would be fairly easy to change serializers to extend the JsonSerializer class, and do something similar in them.

dbc
  • 104,963
  • 20
  • 228
  • 340
Mark W
  • 2,791
  • 1
  • 21
  • 44
  • Doing it this way (with mapper visibility settings) requires us to make structural changes to our Java that tightly couple our code to this particular serialization case. There are lots entities involved here and this is a cross cutting concern, so we'd prefer to accomplish it with annotations if possible. I see jackson ContextualSerializer for checking annotations, I'm going to have a go at using that to do conditional serialization based on a custom annotation. – alba lion Oct 03 '14 at 12:01