Feature: JSON Views

http://wiki.fasterxml.com/JacksonJsonViews

Feature: JSON Views


Idea

思路
java

"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).
git

“Views”,在这个语境中,意思是为将要序列化的逻辑属性(经过get方法或者字段获取到的)定义一个子集。views是经过注解(annotations)来静态定义的,可是使用的时候是动态选择的(每一个须要序列化的地方本身选择使用哪些views)
github


Design

设计
json

  • Views themselves are identified by using Classes, instead of Strings (or dedicated objects). Reasons:app

  • views是使用类来定义的,而不是使用字符串,或者其它某些特定的实例。缘由是:less

    • With classes, can use inheritance to naturally (?) represent View hierarchies (if a field is part of a View, it'll be also part of parent view)ide

    • 使用类,就可使用继承来更加天然的展现views的结构(若是一个字段是某个view的一部分,那么它也是父级view的一部分)this

    • Classes can be used as annotation values: Enums not (Enums would have been one other obvious possibility) spa

    • 类能够用做注解中的值,而枚举不能够(枚举也是另外一个可能用做view的设计)
      设计

    • For future extensibility, classes can also be annotated if need be (no plans for such annotations yet)

    • 考虑将来的扩展性,若是有必要的话,(用做vies定义的)类自己也能够被打上注解(不过不在现有标签的计划中)

  • View membership defined using annotations: specify which view(s)property will be included in. If no view annotation, assumed to mean View identified by Object.class: that is, included in all views

  • 咱们是这样定义视图注解的使用方式的:为某个属性标记上某个注解,标示这个属性将被包含在(最终的json字符串之)内。若是某个属性上没有任何注解,则认为它被标记为“Object.class"的视图,并会被包含在全部视图中。

  • View to use for serialization (and with 2.0, deserialization) is specified dynamically; active view is a property of SerializationConfig (and DeserializationConfig). Conceptually defaults to Object.class; as if no View functionality was used at all.

  • 在序列化为json的过程当中(以及,在2.0中,还包括反序列化的过程),view是动态指定的。一个view是一个SerializationConfig (对反序列化来讲则是DeserializationConfig)的一个属性。这个属性的默认值是Object.class,其功能和不使用view是同样的。

  • Only single active view per serialization; but due to inheritance of Views, can combine Views via aggregation.

  • 每次序列化都只能使用一个视图;可是,考虑到视图的继承层次,能够把多个视图组合成一个。

  • All view membership inclusive, no need for exclusions? (however: could add an option to change default handling of 'unmarked' properties to mean "don't include unless specifically identified)

  • view的用法都是“包含在序列化结果”中的,没有“排除在序列化结果以外”的语义。(不过,能够增长一个选项来改变对“unmarked”属性的默认处理方式——把它改为“除非特别声明,不然不把被标记属性包含在序列化结果中”)


Implementation

实现

1.4 implementation is used as follows.

1.4版的实现是这样使用的。

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。你能够重用现有的类或view,或者只建立一些“虚假的类”——所谓“虚假”是指,这些类只用来标识view以及view的依赖和关联(例如,子view会继承父view的信息)。如下是代码:

  // 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:

定义好这些view以后,序列化过程会这样执行:

  // 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'.

而且,最终结果会仅仅包含“name”,而没有“address”或“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.

注意:即便你只想使用“默认”view——也就是说,


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

相关文章
相关标签/搜索