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);
}
}
Jackson can't deserialize into private fields with its default settings. Because it needs getter or setter methods.
Default jackon behaviour seems to use both properties (getters and setters) and fields to serialize and deserialize to json.
You definitely don't need all those @jsonProperty . Jackson mapper can be initialized to sereliazie/deserialize according to getters or private members, you of course need only the one you are using.
Jackson Annotations - @JacksonInject @JacksonInject is used when a property value is to be injected instead of being parsed from Json input. In the example below, we are inserting a value into object instead of parsing from the Json.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With