duffymo
duffymo

Reputation: 308793

Does Jackson Without Annotations Absolutely Require Setters?

I'm using Jackson 1.6.4 and Java JDK 6.

I don't want to use Jackson annotations; I want to have immutable Java objects without setters.

The two requirements appear to conflict.

If I add private setters deserialization works fine.

I'm trying to not resort to private setters for my immutable objects - I'm stubborn that way.

I'm in the process of trying a custom implementation of VisibilityChecker to allow ANY field access.

But if anyone has some advice or lessons learned they can share I'd appreciate hearing them.

UPDATE: It's working.

Builder pattern, private constructor - a la Bloch "Effective Java".

It took setting deserialization configuration and visibility, but now it's good to go.

public class JsonMapper
{
   private static final int INITIAL_SIZE = 2048;
   /** See http://wiki.fasterxml.com/JacksonBestPracticeThreadSafety?highlight=(\bCategoryJackson\b) */
   private static ObjectMapper mapper;

   static
   {
      mapper = new ObjectMapper();

      mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
      SerializationConfig serializationConfig = mapper.getSerializationConfig();
      serializationConfig.setDateFormat(Person.DEFAULT_FORMATTER);

      mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES,false);
      DeserializationConfig deserializationConfig = mapper.getDeserializationConfig();
      deserializationConfig.setDateFormat(Person.DEFAULT_FORMATTER);
      deserializationConfig.enable(DeserializationConfig.Feature.AUTO_DETECT_FIELDS);
      mapper.setVisibilityChecker(VisibilityChecker.Std.defaultInstance().withFieldVisibility(JsonAutoDetect.Visibility.ANY));
   }

   public static <T> String serialize(T o) throws IOException
   {
      StringWriter sw = new StringWriter(INITIAL_SIZE);
      mapper.writeValue(sw, o);

      return sw.toString();
   }

   public static <T> T deserialize(String source, Class<T> targetClass) throws IOException
   {
      ByteArrayInputStream stream = new ByteArrayInputStream(source.getBytes());
      TreeTraversingParser treeTraversingParser = new TreeTraversingParser(mapper.readTree(stream));
      treeTraversingParser.setCodec(mapper);

      return treeTraversingParser.readValueAs(targetClass);
   }
}

Upvotes: 19

Views: 14918

Answers (1)

StaxMan
StaxMan

Reputation: 116522

Glad to hear you made it work -- ability to change auto-detection visibility levels is a very powerful feature, but there are so many features that it is not trivial to find all there is.

Couple of additional pointers: if you do not want to add Jackson annotations in POJOs, you can still use mix-in annotations. With this, you can use @JsonCreator to specify non-default constructor to use which allows true immutable value types (more on Jackson and immutable types on this article).

And finally: while builder pattern is not yet directly supported, it has been planned as per this Jira entry.

Upvotes: 18

Related Questions