Jackson JSON Processor
  1. Jackson JSON Processor
  2. JACKSON-138

Add something like @JsonView annotation, matching setting for serializer, to allow serializing subset of properties

    Details

    • Type: New Feature New Feature
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 1.4
    • Component/s: None
    • Labels:
      None
    • Number of attachments :
      0

      Description

      (note: sort of related to JACKSON-108)

      Users have requested a way to allow serializing different subsets of properties of objects, by defining "views". This can be implemented by annotating properties (fields or getter-method induced ones) with one or more views that include them. Views are simply classes, to work well with annotations but provide both bit of static type safety, and simple hierarchy.
      On serialization, active view needs to be specified (default being 'none', i.e. all possible properties are serialized – equal to passing Object.class as view (since that is super class of all objects)).

      Match between serialization view and view(s) property is included in can be done using normal class assignment rules: active view has to be assignable from one of views property is member of. That is; property view can be a sub-class of active view, but not vice versa.

        Activity

        Hide
        David Yu added a comment -

        Any of those 2 approaches you mentioned will work fine.

        Thanks

        Show
        David Yu added a comment - Any of those 2 approaches you mentioned will work fine. Thanks
        Hide
        Tatu Saloranta added a comment -

        Ok. I am hoping to find some way to do more on-demand static analysis – that is, determine possible views when serializer/deserializer is constructed. Or at least a way to know a priori of a type might have View definitions. That could be done with both approaches, although would require configuration of a single filter (or all views) before first data binding.
        This is one reason why annotations are nice from framework's perspective: they will be available right away (except for mix-ins, but they are registered via ObjectMapper).

        But I think that may be ability to register filters (both by simple Class-to-filter definition via config objects; and via new property of JsonSerialize/Deserialize annotations) would be the way to go. The filter itself can still do as dynamic filtering as it wants to, given View identifier (Class, as with annotation-based views).
        This would be more flexible than enumerating field names, yet still allow defining specific filter implementation that could be instantiated with a field name list.

        Show
        Tatu Saloranta added a comment - Ok. I am hoping to find some way to do more on-demand static analysis – that is, determine possible views when serializer/deserializer is constructed. Or at least a way to know a priori of a type might have View definitions. That could be done with both approaches, although would require configuration of a single filter (or all views) before first data binding. This is one reason why annotations are nice from framework's perspective: they will be available right away (except for mix-ins, but they are registered via ObjectMapper). But I think that may be ability to register filters (both by simple Class-to-filter definition via config objects; and via new property of JsonSerialize/Deserialize annotations) would be the way to go. The filter itself can still do as dynamic filtering as it wants to, given View identifier (Class, as with annotation-based views). This would be more flexible than enumerating field names, yet still allow defining specific filter implementation that could be instantiated with a field name list.
        Hide
        Tatu Saloranta added a comment -

        Finally got this implemented. I was hoping to make things more dynamic, with pluggable handlers, but in the end this is not quite how it works; partly because of annotation limitations.
        However, it is possibly to plug-in alternate serialization view filters at low level (by modifying BeanSerializers, esp. when BeanSerializerFactory constructs them), which allows some level of custom view handling.

        Anyway: the standard method uses new @JsonView annotation, attached to properties; and SerializationConfig.setSerializationView (plus convenience methods in ObjectMapper). Something like:

        StringWriter sw = new StringWriter();
        ObjectMapper mapper = new ObjectMapper();
        // with fewer fields:
        mapper.writeValueUsingView(sw, new Bean(), DefaultUserView.class);
        // and full
        mapper.writeValueUsingView(sw, new Bean(), AdminView.class);

        with something like:

        static class DefaultUserView { } // just a marker; can sub-class etc
        static class AdminView extends DefaultUserView { } // just a marker; can sub-class etc
        class Bean

        { @JsonView(DefaultUserView.class) public int publicId; @JsonView(AdminView.class) public String internalId; // only for admin views }
        Show
        Tatu Saloranta added a comment - Finally got this implemented. I was hoping to make things more dynamic, with pluggable handlers, but in the end this is not quite how it works; partly because of annotation limitations. However, it is possibly to plug-in alternate serialization view filters at low level (by modifying BeanSerializers, esp. when BeanSerializerFactory constructs them), which allows some level of custom view handling. Anyway: the standard method uses new @JsonView annotation, attached to properties; and SerializationConfig.setSerializationView (plus convenience methods in ObjectMapper). Something like: StringWriter sw = new StringWriter(); ObjectMapper mapper = new ObjectMapper(); // with fewer fields: mapper.writeValueUsingView(sw, new Bean(), DefaultUserView.class); // and full mapper.writeValueUsingView(sw, new Bean(), AdminView.class); with something like: static class DefaultUserView { } // just a marker; can sub-class etc static class AdminView extends DefaultUserView { } // just a marker; can sub-class etc class Bean { @JsonView(DefaultUserView.class) public int publicId; @JsonView(AdminView.class) public String internalId; // only for admin views }
        Hide
        Tatu Saloranta added a comment -

        Implemented, will be released in 1.4.0.

        Still need to test customized filters, document, but that's not strictly part of this task.

        Show
        Tatu Saloranta added a comment - Implemented, will be released in 1.4.0. Still need to test customized filters, document, but that's not strictly part of this task.
        Hide
        Tatu Saloranta added a comment -

        Included in 1.4.0 release.

        Show
        Tatu Saloranta added a comment - Included in 1.4.0 release.

          People

          • Assignee:
            Tatu Saloranta
            Reporter:
            Tatu Saloranta
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: