4

Hi I have few UI objects that embedded into each other. Example #1:

class CarUI {
  public UserUI user;
  public UserUI agent;
  ....
  public UserUI getUser() {
    return user;
  }
  public UserUI getAgent() {
    return agent;
  }
}
class UserUI {
  @JsonView({Views.Public.class,Views.Private.class})
  public String name;
  @JsonView({Views.Private.class})
  public String phone;
  ...
}

As you can see if I serialize UserUI as Public I will expose only name but for private I will expose all fields.

Here is my question: when I serialize object CarUI I want to expose only name for "user" and both name+phone for "agent". That essentially means that in the getter for the getUser() I want to change JsonView to Views.Public.class and for getAgent() I want to change it to Views.Private.class

Is there way to overwrite JsonView in getters to make all hierarchy for the returned object now serialize using this new JsonView?

Edited As pointed below you can solve my Example#1 with JsonView inheritance. What about more generic. Here is Example#2:

class CarUI {
  public UserUI user;
  public UserUI agent;
  ....
  public UserUI getUser() {
    return user;
  }
  public UserUI getAgent() {
    return agent;
  }
}
class UserUI {
  @JsonView({Views.Public.class,Views.Private.class})
  public String name;
  @JsonView({Views.Private.class})
  public String phone;
  @JsonView({Views.Public.class})
  public String avatarUrl;
  ...
}

In this example Id like to display name+phone for Agent and name+avatarUrl for User.

Andrei V
  • 1,468
  • 3
  • 17
  • 32

2 Answers2

3

@JsonView accepts inheritance. Views.Private fields extends Views.Public fields. This means Views.Private serialization will also look for the Views.Public annotations.

public Views {
    public Public {}
    public Private extends Public {}
}

class CarUI {
  public UserUI user;
  public UserUI agent;
  ....
  @JsonView(Views.Public.class)
  public UserUI getUser() {
    return user;
  }
  @JsonView(Views.Private.class)
  public UserUI getAgent() {
    return agent;
  }
}

class UserUI {
  @JsonView(Views.Public.class)
  public String name;
  @JsonView(Views.Private.class)
  public String phone;
  ...
}

For Example #2

You can introduce multiple classes like:

public Views {
    public Public {}
    public Private1 extends Public {}
    public Private2 extends Public {}
}

class CarUI {
  public UserUI user;
  public UserUI agent;
  ....
  public UserUI getUser() {
    return user;
  }
  public UserUI getAgent() {
    return agent;
  }
}
class UserUI {
  @JsonView(Views.Public.class)
  public String name;
  @JsonView({Views.Private1.class})
  public String phone;
  @JsonView({Views.Private2.class})
  public String avatarUrl;
  ...
}

Or you can use view-less properties and use no inheritance:

public Views {
    public Public {}
    public Private {}
}

class CarUI {
  public UserUI user;
  public UserUI agent;
  ....
  public UserUI getUser() {
    return user;
  }
  public UserUI getAgent() {
    return agent;
  }
}
class UserUI {
  // This one is view-less shows every time unless you specificy
  public String name;
  @JsonView({Views.Private.class})
  public String phone;
  @JsonView({Views.Public.class})
  public String avatarUrl;
  ...
}

...
// If you want to hide view-less properties, default is true 
objectMapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION, false); 
...
Ghokun
  • 3,345
  • 3
  • 26
  • 30
  • Thank you. That will work for my example where 2 JsonViews overlap on properties. What if Public has property that Private does not have and opposite. See above Example #2. – Andrei V Oct 27 '15 at 18:14
  • Edited my answer. Tried to use multiple classes in @JsonView annotation however no luck in there. – Ghokun Oct 28 '15 at 09:58
1

Just found more generic case if anyone need. Basically you can transform your property inside getter using different JsonView as such:

  @JsonView({ Views.Detail.class})
  public JsonNode getAgent() throws IOException {
      ObjectMapper mapper = new ObjectMapper();
      String json = mapper.writerWithView(Views.Private.class).writeValueAsString(agent);
      return mapper.readTree(json);
  }
Ortomala Lokni
  • 56,620
  • 24
  • 188
  • 240
Andrei V
  • 1,468
  • 3
  • 17
  • 32