Contents
General
Processing Models
Which processing models (streaming, tree, objects) does Jackson implement?
Three main methods (one with 2 alternatives) are implemented:
Streaming/incremental parsing (reading) and generation (writing) of JSON content
Tree model (based on JsonNodes)
Data binding to/from Java objects (POJOs, Beans, primitives, lists/arrays/maps)
alternative "untyped" binding to only use Lists/Maps/String/Boolean/Number/null (bind to Object.class)
Most other Java JSON packages only implement one or two of modes: for example, Json.org Reference Implementation just offers access via its custom tree model.
Which mappings (Badgerfish, natural, ...) does Jackson implement?
None. Jackson is "100% JSON" and does not try to imitate or emulate XML. Property name mapping is based on standard Java Bean naming convention (although can be overridden using annotations or custom naming strategy).
There are some support compatibility features -- such as ability to optionally use JAXB annotations -- but fundamentally Jackson is a pure JSON/Java data mapper and tries to minimize impedance between JSON and Java data models.
Data Formats
In addition to textual (standard) JSON, there are also Jackson readers/writers that allow processing JSON-like content that uses other data formats:
Starting with Jackson 1.6, Jackson supports JSON-compatible binary data format called Smile, using SmileFactory, and JsonParser / JsonGenerator implementations that can read/write Smile format.
Dependencies
Platform
Which JDK does Jackson require?
JDK 1.5 or above -- this because it makes heavy use of enum types, generics and annotations.
Jackson should also work on "almost JDK 1.5" level platforms such as Google Android and GAE (to the degree missed pieces of functionality can be worked around).
External
Does Jackson depend on other libraries outside of JDK?
No: neither Jackson core nor data mapper have runtime dependencies on external libraries.
Other Jackson jars depend on APIs that may or may not be included in JDK (depending on version), such that:
Jackson-xc depends on JAXB API (javax.xml.bind) which is bundled with JDK 1.6 and above (for 1.5, you need JAXB api jar)
Jackson-jaxrs depends on JAX-RS API (javax.ws.rs) which is not (yet) bundled with JDK: a separate API jar is needed; this is usually provided with JAX-RS implementation package is used
with.
Starting with 1.6, Jackson also embeds ASM bytecode manipulation library as part of "Mr Bean" extension. Code is repackage using jarjar to avoid conflicts with possible other instances of ASM that may exist in Java classpath.
But I saw some warnings about failing to load Joda DateTime classes?
Later versions (1.4 and above) do offer basic support for some well-known libraries and frameworks, so that there are more compile-time dependencies. During runtime, however, loading is done in a way that missing those libraries should fail gracefully; that is, functionality related to these libraries is not available, but everything else works as expected.
However: some runtimes (reportedly at least Android's JVM, Dalvik), complain about failures to locate classes dynamically. These warnings can be annoying but they are not fatal. Additionally these are platform problem -- Java VM design specifically supports the idea of dynamic discovery, so Jackson's use of dynamic class discovery and loading is solid -- which would be good to bring attention to developers of said platforms. Jackson development team will also gladly accept suggestions for improved handling by Jackson.
Data Binding, general
What mechanism does Jackson use for binding?
Jackson 1.0 supports Bean method - based binding, where serialization requires "getter" methods, and deserialization "setters" (with optional "creator" methods). Version 1.1 also supports direct access of member fields (public instance fields, annotated instance fields).
Also: as of version 1.2, Jackson allows use of "Creator" methods (constructors and static factory methods), which means that it is possible to omit setter methods if data is to be passed via constructor.
How does Jackson map JSON properties to Java methods/fields?
The default mechanism is to use implied name as per Bean convention – for getters and setters leave out "get" or "set", lower case first char – but this can be overridden by annotations (@JsonSetter/@JsonGetter for Jackson 1.0, alternatively @JsonProperty for Jackson 1.1).
With version Jackson 1.1, it is also possible to use subset of JAXB annotations to denote getter and setter methods and fields.
How can I configure data binding aspects?
There are multiple ways to do this:
Configure ObjectMapper used for binding, enabling/disabling features defined by SerializationConfig.Feature and DeserializationConfig.Feature
Configure JsonFactory instance ObjectMapper uses
- Use annotations:
Optional, starting with 1.1, you can also use JAXB annotations in addition to or instead of core Jackson annotations.
But I can not modify existing classes to add annotations!
No problem: this is exactly why we added Mix-In Annotation support, so that you can associate annotations as if they were included in class definition, but without having to do that (hence "mix-in" in name). This gives you full power of type-safe annotation-based configuration, but with less tight coupling.
Is ObjectMapper thread-safe?
Short answer: yes
Long answer: yes, as long as you always configure instance before use, and do not call configure methods during operation (or synchronize such calls appropriately). Usually it is better to construct separate mapper instance if configurations differ in any case.
Further: it is beneficial to use just one instance (or small number of instances) for data binding; many optimizations for reuse (of symbol tables, some buffers) depend on ObjectMapper instances being reused.
For more information, check out JacksonFAQThreadSafety
Data Binding, writing (serialization)
Serializing values as simple types
Instead of serializing Java Objects as JSON Objects (via Bean introspection), can't I just serialize them as plain JSON Strings?
Yes. Just annotate property (Java field or getter method that implies property) with @JsonValue; for example:
@JsonValue public String toString() { return _value.tosString(); }would make method object.toString() be called to get serialized value. This actually works with any serializable Java types; proper serializer is located based on return type, so there is nothing special about String as type here. See JacksonAnnotations for details on usage.
Serializing Dates
Custom Serializers
Can I write custom deserializers?
You betcha: check out JacksonHowToCustomSerializers for details.
(and probably also JacksonHowToCustomDeserializers if you need to read data back)
Filtering with Serialization
How can I omit property X from being included in serialization?
There are actually multiple ways, such as:
Explicitly mark a property to be ignored using @JsonIgnore (possibly using JacksonMixInAnnotations if you can not modify classes directly)
Listing names of properties of a class to ignore using @JsonIgnoreProperties (likewise can use with mix-ins)
Using JSON Views for defining profiles (Json Views) that specify set of properties to include.
Serializing, Polymorpic types
Why is there no type information when I serialize Lists/Maps?
If you use something like:
HashMap<String, MyPOJO> map = ... mapper.writeValueAsString(map);
and value type (MyPOJO) has @JsonTypeInfo annotation (or so-called "default typing" indicates it needs to include type information), things should seemingly work. But, alas, as far as Java runtime is concerned, you are NOT serializing a Map<String,MyPOJO, but rather something like Map<?,?! This is due to infamous "Type Erasure", which is due to runtime Class NOT retaining type information -- there is just one class, and not one instance per parameterized version.
For full explanation of what happens, why, and how to resolve this, see JacksonPolymorphicDeserialization, Section 5.1 under "Known Issues".
Serializing, other
What is the simplest way to serialize JSON as a String?
Prior to Jackson 1.3, simplest way is to use java.io.StringWriter:
StringWriter sw = new StringWriter(); mapper.writeValue(sw, value); String result = sw.toString();
1.3 introduces a new convenience method, so that you can:
String result = mapper.writeValueAsString(value);
What is the simplest way to serialize JSON as byte[]?
With 1.5: byte[] data = objectMapper.writeValueAsBytes(bean);
Can I omit writing of Bean properties with null value? ("how to prevent writing of null properties")
Yes. As per JacksonAnnotationSerializeNulls, you can use:
objectMapper.configure(SerializationConfig.WRITE_NULL_PROPERTIES, false);
and voila, no more null values. Note that you MUST configure mapper before beans are serialized, since this setting may be cached along with serializers. So setting it too late might prevent change from taking effect.
Alternatively if you only want to change behavior for value of specific type, you can use annotation property:
@JsonSerialize(include = Inclusion.NON_NULL)
public class MyTypeWithoutNulls
{
public String mayHaveValue; // will not be included if value is null
}to achieve the same for the annotated class or property)
Moreover, you can even exclude any properties with default values (values that are set when instance is created with default, no-arg constructor), by calling:
objectMapper.setSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
or for specific classes:
@JsonSerialize(include = Inclusion.NON_DEFAULT)
public class MyTypeWithoutDefaults
{
public int count; // will not be included if value is 0 (default for int)
}
Data Binding, reading (de-serialization)
Deserializing simple types
If I want to deserialize simple JSON values (Strings, integer / decimal numbers) into types other than supported by default, do I need to write a custom deserializer?
Not necessarily. If the class to deserialize into has one of:
- Single-argument constructor with matching type (String, int/double), or
- Single-argument static method with name "valueOf()", and matching argument type
Jackson will use such method, passing in matching JSON value as argument.
Deserializing Dates
Custom Deserializers
Can I write custom deserializers?
Absolutely. Check out JacksonHowToCustomDeserializers.
(and, related to this JacksonHowToCustomSerializers for serialization side)
Deserializing: unknown properties
By default Jackson throws an exception, if it encounters a JSON property that it can not bind to object property. But if you need to allow such properties in input, you can make Jackson ignore them by:
(1.2+): Configure ObjectMapper to globally ignore any unknown properties:
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
(1.4+: Configure classes with @JsonIgnoreProperties to denote which properties are to be ignored (or specify that any unknown are to be ignored without exception)
Register a DeserializationProblemHandler, which can also suppress error notification (by returning 'true' from method handleUnknownProperty)
objectMapper.addHandler(/*DeserializationProblemHandler*/ myHandler);
(for more details, see JacksonHowToIgnoreUnknown)
Deserializing Generic types
Due to Java Type Erasure (losing generics declarations when Classes are compiled), it is NOT possible to specify generic types to bind to. In order to pass full generics type information to, say, bind JSON into List<MyBean>, you have to use methods that take either TypeReference or JavaType. Most commonly former is used; and it is used like so:
List<MyBean> result = mapper.readValue(src, new TypeReference<List<MyBean>>() { });to use JavaType, you need to construct method by passing java.lang.reflect.Type into TypeFactory (check out JavaDocs for details), or:
List<MyBean> result = mapper.readValue(src, TypeFactory.collectionType(ArrayList.class, MyBean.class));
if you don't like anonymous inner classes (you can similarly construct all kinds of generics types, with TypeFactory.parametericType(...)).
Deserializing Abstract types
If a property has abstract type, how can I make it deserialize into proper concrete type?
There are two distinct cases: if you just have a simple one-to-one mapping from abstract type (interface) into concrete implementation, there are multiple ways to handle this, shown below. If you have multiple implementation types, please look at the next question ("deserializing polymorphic types")
There are multiple ways to indicate specific implementation class of an abstract type:
Annotation @JsonDeserialize(as=Impl.class) is a simple way to indicate implementation class, and can be used for both classes (default impl for interface / abstract class annotated) and properties (default type for property value annotated)
For java.util.List values you would use @JsonDeserialize(contentAs=ValueTypeImpl.class) instead, and for java.util.Map keys, @JsonDeserialize(keyAs=KeyTypeImpl.class).
You can also register abstract type mappings using Module interface: when using SimpleModule, you can call: simpleModule.addAbstractTypeMapping(MyInterface.class, MyImpl.class);
Deserializing Polymorphic types
But what if there are multiple subtypes for given declared type?
If there are multiple alternate implementations, you need to enable addition of so-called Type Information. For full description, refer to JacksonPolymorphicDeserialization, but there are two basic approaches:
Use @JsonTypeInfo on base type (or next to property) to indicate that additional type information is to be included when serializing values of annotated type (or property).
Enable "default typing" (using ObjectMapper.enableDefaultTyping()), which works similar to as if @JsonTypeInfo was implicitly added to set of types (set defined by default typing rules: default rule applies it to java.lang.Object and all abstract types)
In both cases what happens is that during serialization, a type identifier (class name or logical configurable type name) is included in JSON (using one of multiple placement strategies; most common being as a simple property). And when deserializing, deserializer expects to find this type identifier and will use it to correctly determine expected type to create, and then deserialize instance of that concrete type.
Deserializing, other
Why do I get these java.util.LinkedHashMap objects when deserializing?
If you expect other types (like POJOs), most likely reason is that you are not providing expected type information, and as a result, Jackson assumes what you want is basic java.lang.Object. This can be done by mapping JSON Objects as Java Maps, JSON Array as Java lists, JSON numbers as java.lang.Number and so on.
The most common reason is so-called Java Type Erasure, meaning that generic type information that you think should be available is not. For example, following does NOT work as expected:
Map<String, MyBean> beansByName = objectMapper.readValue(json, Map.class);
since this is equivalent to asking for binding to Map<?,?>); and type wildcard '?' can only be assumed to be of some Object type.
Instead, you have to specify generic parameters, for example by doing:
Map<String, MyBean> beansByName = objectMapper.readValue(json, new TypeReference<Map<String, MyBean>>() { });and then values will be of type MyBean, not LinkedHashMap.
Can I deserialize multiple distinct objects?
Q: (from mailing list)
My JSON payload has multiple objects like so -
{
"university": {
"name":"MIT", ...
},
"lecturer": {
"firstName":"Joe","lastName":"Public", ...
}
}I want to de-serialize the JSON object mapped to the key "university" to University.class and I would like to de-serialize the JSON object mapped to key "lecturer" to Lecturer.class. What is the best way to do this?
A:
Two ways to do this:
(a) Create 'dummy' class like
public class Container {
public University univ;
public Lecture lect;
}- and bind using it, or
(b) Use JsonParser; skip through JsonToken.START_OBJECT, match JsonToken.FIELD_NAME}}, then call {{{readValueAs() with appropriate type. NOTE: if you use this approach, make sure to use MappingJsonFactory for constructing parser, NOT plain JsonFactory!
Can I use JAXB-style Map/Collection access
(that is: modify Map or Collection properties by calling get, modifying instance directly, without calling matching set method)
Yes: if there is only a getter method for Map/Collection - valued property, and no setter method, Jackson will try to use this mechanism. This behavior can be disabled by disabling DeserializationConfig.USE_GETTERS_AS_SETTERS; although without a setter there will be an exception if such a property was to be deserialized.
Alternatively, if you really want to use this style even if there is a setter method, you will need to suppress use of setter itself. This can be done using @JsonIgnore annotation on setter.
Streaming (incremental) Processing
Problems with String intern()ing
How to avoid "java.lang.OutOfMemoryError: PermGen space" problem?
(modified from a question on Jackson user list)
Q: (from user list)
My application is getting a "java.lang.OutOfMemoryError: PermGen space" error. I tracked this down due to "interned" strings from Jackson while parsing. I believe this is due to some of my input being a map that can have arbitrary key values. What can I do to avoid this?
A:
By default Jackson canonicalizes key names (i.e. tries to ensure all instances of a field name use same String instance); and does this by using String.intern(). Canonicalization is done using a per-JsonFactory shared symbol table; and can help both reduce memory usage and speed up parsing (since can avoid String allocation as well as character decoding in most cases).
However, it is possible to both:
Disable use of String.intern() for materialization (symbol table is still maintained; but its size is bounded): JsonParser.Feature.INTERN_FIELD_NAMES (since Jackson 1.3)
Disable any canonicalization (regardless of methods): in this case a new String is allocated for each field name: JsonParser.Feature.CANONICALIZE_FIELD_NAME (since Jackson 1.5
Disabling String intern()ing should be enough to resolve running out of PermGen space; and in general should be enough to avoid excessive memory usage (that is, we have not yet seen any case where it would not). But if you truly think it is not enough, you should try just disabling whole canonicalization. Note that both these options have negative effects on performance in cases where same field names are parsed multiple times (including cases where these are in different documents, but parsers were created by the same factory and thus share the symbol table); effect can be particularly significant if all canonicalization is disabled. Disabling intern()ing should have less effect.
Check out Streaming/incremental API page for even more information.
Tree Model
Node equality?
Can I compare JsonNode instances for equality? (and by extension: "Can I compare full JSON trees by just comparing root nodes")
Yes! JsonNode instances implemented expected deep value comparison, using expected conceptual rules (like: order of JSON Object properties is insignificant for equality, but matters for JSON Arrays).
So you can compare equality of JSON trees by just comparing root nodes like so:
boolean areEqual = tree1RootNode.equals(tree2RootNode);
(TO BE COMPLETED)
Check out Tree model page for even more information.
Compatibility with Other Things
Non-Java JVM languages
Can Jackson be used from non-Java languages that run on JVM?
Yes. In addition to being used from Java, Jackson has been reported to work from various other JVM-based languages, such as:
- Scala (note: there is now a new sub/side-project to add full support; see below)
- Groovy
(note: would be nice to have links to articles or mailing list messages for these reports)
More specifically, there are now (as of Jackson 1.7) multiple projects that aim to add full support; see Jackson Module Projects page for up to date information.
Alternative data formats
Beyond supporting JSON (and Smile binary format, which is fully JSON compatible), there are related projects that aim to support other data formats. See JacksonOutsideofJSON page for details.
Frameworks
JAX-RS
Can I use Jackson to do JSON serialization with JAX-RS?
Yes. Starting with Jackson 1.0, there is jar (jackson-jaxrs-VERSION.jar) that implements JAX-RS MessageBodyReader and MessageBodyWriter, needed for converting Java beans to/from JSON.
NEW: With version 1.3, there is an improved JAX-RS provider available, org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider; which by default uses both JAXB and Jackson annotations. This can be used in place of earlier JacksonJsonProvider (which is its super-class), and provides extended set of configuration methods. It does depend on features from jax-xc package, so make sure it is also included if using this new provider.
In addition to adding jackson-jaxrs jar (and jackson core and mapper jars it depends on, if not bundled by the JAX-RS implementation), you will also need to register provider. There are 2 ways to do this:
Add root provider with JAX-RS registration mechanism; for example, by returning provider class/instance from Rest Application class.
Add 'META-INF/services/javax.ws.rs.ext.MessageBodyReader' file with one entry, provider class name (org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvide) (and similarly for MessageBodyWriter) to a jar that gets loaded by JAX-RS implementation (this can be done by post-processing jackson-jaxrs jar, for example).
Here's one implementation of the first approach:
import java.util.*;
public final class RestApplication extends javax.ws.rs.core.Application
{
public Set<Object> getSingletons() {
HashSet<Object> singletons = new HashSet<Object>();
singletons.add(new org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider());
return singletons;
}
}Which JAX-RS implementations are Jackson known to work well with?
Jersey (tested by dev team)
RESTeasy (tested by dev team)
Apache CXF (reported by CXF dev team)
And there is more on JAX-RS interoperability to learn...
JAXB
Jackson supports some level of interoperability with JAXB API (javax.xml.bin):
With Jackson 1.1, it is possible to use JAXB annotations in addition to (or instead of) core Jackson annotations
- In addition to setting Map and Collection properties, it is also possible to do 'JAXB style' "modify-via-get" access (call getter-method to get Map/Collection instance, modify directly, not call setter method at all): this is enabled by default, used iff no setter is located for a Map/Collection property (but getter is found).
Can be disabled using DeserializationConfig.USE_GETTERS_AS_SETTERS (enabled by default)
Object/Relational Mappers (ORM)
Jackson has been used with some success with:
(might also work with Hibernate, but this has not been verified yet)
As of Jackson 1.7, there is a also a new project, Jackson XML data binding (see JacksonOutsideofJSON for other extension projects) that adds significant subset of JAXB functionality (wrt reading/writing XML) to Jackson.
Spring
Spring-WS / MVC 3.0 has specific support using Jackson for JSON data binding access.
Articles that describe usage:
Mule ESB
Mule ESB version 3.0 will have support for JSON via Jackson, see:
"Using JSON bindings with iBeans" (iBeans/Mule)
Apache Camel
This article explains how to use Jackson with Apache Camel:
Javascript frameworks
Since Javascript frameworks work on client side, and Jackson on server side, interoperability is usually less problematic. Here some notes on observer interoperability issues.
Ext JS
Default date/time serialization format of Ext JS seems to use ISO-8601 dates without timezone specification. This is problematic since this can be interpreted to mean "local time zone" of the end point, whatever that might be. However, it is possible to re-define this default; for example by: (cut'n pasted from an example sent to Jackson user list by Scott A)
// It's very straightforward to override their treatment of dates:
Ext.util.JSON.encodeDate = function(o)
{
return '"' + yourEncodingHere + '"';
}
Performance
How does Jackson perform?
Rather nicely. It seems to be the fastest JSON processing package on Java platform, for all processing models. Streaming parser, for example, appears to be 3 - 5x faster than most alternatives (although there are some other fast ones, such as Noggit, but none quite compete). And data binding up to 10x faster as alternatives.
But more useful than our claims are published measurements and performance evaluations. For example:
JSON vs Protobuf, Thrift, XML: comparison of various formats, libraries -- see Json+Jackson entries
Members of the Jackson development team have also published some performance measurements:
Update on State of Json-parsing Performance measures performance of streaming parsing, as well as compares it to other models.
JSON data binding performance: Jackson vs Google-gson vs BerliOS JSON Tools measures data binding performance
How can I ensure Jackson runs as fast as possible?
See JacksonBestPracticesPerformance for some suggestions.
Misc
MIME Type for Smile (binary)?
There is no formal registration for Smile content type; but the best current suggestion appears to be application/x-jackson-smile. We suggest you use this type if possible; and when more formal proposal is made, this recommendation will be upgraded as well.
