Feature: JSON Views

Idea

"Views" in this context mean ability to define subsets of logical properties (things accessed via getters or fields) to serialize. Views are defined statically (using annotations), but view to use for serialization is chosen dynamically (per serialization).

Design

Implementation

1.4 implementation is used as follows.

First, defining views means declaring classes; you can reuse existing ones, or just create bogus classes -- they are just view identifiers with relationship information (child inherits view membership from parents):

  // View definitions:
  class Views {
            static class Public { }
            static class ExtendedPublic extends PublicView { }
            static class Internal extends ExtendedPublicView { }
  }
          
  public class Bean {
            // Name is public
            @JsonView(Views.Public.class) String name;
            // Address semi-public
            @JsonView(Views.ExtendPublic.class) Address address;
            // SSN only for internal usage
            @JsonView(Views.Internal.class) SocialSecNumber ssn;
  }

With such view definitions, serialization would be done like so:

  // short-cut:
  objectMapper.writeValueUsingView(out, beanInstance, ViewsPublic.class);

  // or fully exploded:
  objectMapper.getSerializationConfig().setSerializationView(Views.Public.class);
  // (note: can also pre-construct config object with 'mapper.copySerializationConfig'; reuse)
  objectMapper.writeValue(out, beanInstance); // will use active view set via Config

  // or, starting with 1.5, more convenient (ObjectWriter is reusable too)
  objectMapper.viewWriter(ViewsPublic.class).writeValue(out, beanInstance);

and result would only contain 'name', not 'address' or 'ssn'.

NOTE: even if you only want to use "default" view -- that is, just exclude things that are only to be included in specific "full" view -- you DO need to enable View processing by specifying a view. If you do not have explicit "basic" view setting, just use Object.class.

Handling of "view-less" properties

By default all properties without explicit view definition are included in serialization. But starting with Jackson 1.5 you can change this default by:

  objectMapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION, false);

where false means that such properties are NOT included when enabling with a view. Default for this property is 'true'.

Customization

Although default implementation is not very customizable, underlying design does allow for implementing elaborate custom filtering, using alternative means of defining custom views. Here is how.

Enabling "view" processing

Depending on exactly how custom serialization is implemented, you may (or may not) need to enable view processing. If it is needed, you will just do something like:

  ObjectWriter w = objectMapper.viewWriter(SomeClass.class); // 1.8 and prior
  ObjectWriter w = objectMapper.writerWithView(SomeClass.class); // 1.9 and above

which offers same set of writeValue (and writeValueAsString, writeValueAsBytes, ...) write methods and can be reused easily (or passed).

As of 2.0 this is also available for deserialization, like so:

  ObjectReader r = objectMapper.readerWithView(SomeClass.class); // 2.0 and above

Views with JAX-RS

With 2.3 (of JAX-RS module) it is also possible to annotate JAX-RS resources like so:

    public class Resource {

      @JsonView(Views.Public.class)
      @GET
      @Produces(MediaType.APPLICATION_JSON )
      public List<Object> getElements() {
        ...
        return someResultList;
      }
    }

so that you need not try to configure active view via ObjectReader / ObjectWriter.

How to plug in custom View processing?

What you need to implement is a sub-class of org.codehaus.jackson.map.ser.BeanPropertyWriter: this is what standard JsonView does; and make SerializerFactory (usually BeanSerializerFactory) construct BeanSerializer with customized versions. Once this is done, you can control output during serialization as you want.

There is some sample code (src/sample/CustomSerializationView.java) to show how exactly this is done.

Or with 1.7, even better way would be to use JacksonFeatureJsonFilter, which finally gives full dynamic control for application. Annotation is needed for value types, to indicate logical filter id to use, but mapping from id to filter is fully dynamic (on per-call basis if necessary).


CategoryJackson

JacksonJsonViews (last edited 2014-04-23 18:12:34 by TatuSaloranta)

Copyright ©2009 FasterXML, LLC