Affects: \

This limitation should relate to the way @JsonView annotation was implemented in spring: @https://github.com/spring-projects/spring-framework/issues/11815

@JsonView annotation allows to specify multiple views for a class or field using this syntax:

@JsonView({View1.class, View2.class, View3.class})
private java.util.List<Person> persons=null;

By design Spring does not interpret the syntax fully, as it is ignoring multiple view classes in the @JsonView array annotation {}

Code sample:


@JsonView({EventDate.EventPrivateViews.ClientEventServiceRequirement_PutView.class, ObjectPublicViews.Attributes_Roles.class})
@RequestMapping(value = "/eventDate/{eventDateId}", method = {RequestMethod.GET})
public ResponseEntity<EventDate> getEventDate(@PathVariable( name = "eventDateId") Integer eventDateId) {
    EventDate eventDate = ovEventDateCrudService.retrieveById(EventDate.class, eventDateId);
    ResponseEntity<EventDate> ret = new ObjectViewResponseEntity<>( eventDate, HttpStatus.OK );
    return ret;
}

ObjectPublicViews.Attributes_Roles.class (and any other view classes in the array) is ignored, just first one is taken into account Code will behave like having just one view class:

@JsonView({EventDate.EventPrivateViews.ClientEventServiceRequirement_PutView.class})
@RequestMapping(value = "/eventDate/{eventDateId}", method = {RequestMethod.GET})
public ResponseEntity<EventDate> getEventDate(@PathVariable( name = "eventDateId") Integer eventDateId) {
    EventDate eventDate = ovEventDateCrudService.retrieveById(EventDate.class, eventDateId);
    ResponseEntity<EventDate> ret = new ObjectViewResponseEntity<>( eventDate, HttpStatus.OK );
    return ret;

}

This is how sample domain classes might look like:

public class EventDate extends ESDomainObject  
{ 

@JsonView(ObjectPublicViews.Attributes.class)
    private java.lang.Integer eventDateId=null;

@JsonView({ObjectPublicViews.Attributes_Roles.class, ObjectPrivateViews.Attributes_Roles_eventServiceCategories.class, EventPrivateViews.ClientEventServiceRequirement_PutView.class})
    private java.util.List<EventServiceCategory> eventServiceCategories=null;
}
EventDate inner class: 
public static final class EventPrivateViews {
    public static class ClientEventServiceRequirement_PutView extends ObjectPublicViews.Attributes {}
}

and down the road in :

public class EventServiceCategory extends ESDomainObject  { 

    @JsonView(ObjectPublicViews.Attributes.class)
    private java.lang.Integer serviceCategoryId=null;

@JsonView({ObjectPublicViews.Attributes_Roles.class, ObjectPrivateViews.Attributes_Roles_eventRequirements.class, EventPrivateViews.ClientEventServiceRequirement_PutView.class})
    private java.util.List<EventRequirement> eventRequirements=null;
} 

and so on to assemble an object graph (tree)

This limitation of Spring's handling of @JsonView in controller methods could not exactly be a defect but rather a design decision, where each endpoint corresponds to a specific view of the data. Maybe idea was to simplify the controller's logic by binding a single view to an endpoint.

However, since JSON does provide such annotation syntax, and because developers may have already defined all JSONViews for each particular association, it would be beneficial to construct a controller JSON view from existing defined views. Consider a scenario where you need to save an object graph to a database, and graph navigation is performed through reachability.

In such cases, a solution to this limitation in Spring is to statically create a new @JsonView (EventPrivateViews.ClientEventServiceRequirement_PutView.class in sample code) or add this new view class to an existing @JsonView annotation and repeat process for each class down the object graph tree using this new View class. This process must be repeated for each new graph view of the existing data (leading to domain recompilation and so on). Additionally, the number of combinations can grow to the point where they become unmanageable. This is the solution I adopted in the included sample classes above.
Instead, developers should be able to assemble a new object graph view from existing discrete association-defined views.

I understand that there might be other solutions to overcome this challenge, but it's worth noting that developers often use an injected ObjectMapper per controller instance and prefer not to handle that instance directly, let alone create new instances for each REST call (...out of question) to handle dynamic situations that cannot be managed by annotations.

So, it would be nice to be able to dynamically specify an array with classes for the JsonView annotation for the controller.

@JsonView({EventDate.EventPrivateViews.ClientEventServiceRequirement_PutView.class, ObjectPublicViews.Attributes_Roles.class})

In such case spring should analyze the view classes and spring ObjectMapper autowired instance should lazy initialize the object graph (tree) before serialization (as it does now), but this time taking into account all specified view classes. It should parse the annotations and create a union (set) for the final view with all related attributes. ObjectMapper should not retain any configuration state (like it correctly does now) for this dynamic view.

Some ideea: ObjectWriter writer = objectMapper.writerWithView(spring_internally_assembled_view);

Comment From: sdeleuze

As documented, the fact that Spring supports a single view per @JsonView is by design and there is no plan to change that, so I am likely going to decline your request.

@JsonView allows an array of view classes, but you can specify only one per controller method. If you need to activate multiple views, you can use a composite interface.

This is because Spring reuses Jackson @JsonView where this array was designed for the domain model use case, and you can see that ObjectMapper#writerWithView only takes a single class parameter.

ObjectPublicViews.Attributes_Roles.class (and any other view classes in the array) is ignored, just first one is taken into account

Spring should not silently ignore such @RequestMapping level @JsonView with an array, and should throw an error, like JsonViewRequestBodyAdvice or MappingJackson2MessageConverter do.

Could you please provide a reproducer that demonstrates that behavior as an attached project or a link to a repository?

Comment From: faurad

You are right, I understand the design decision, I will close this and apologize for the time you spent.

Best, Adrian