我正在寻找仅在某些情况下序列化瞬态信息的可能性:
@JsonInclude(Include.NON_NULL)
@Entity
public class User {
public static interface AdminView {}
... id, email and others ...
@Transient
private transient Details details;
@JsonIgnore // Goal: ignore all the time, except next line
@JsonView(AdminView.class) // Goal: don't ignore in AdminView
public Details getDetails() {
if (details == null) {
details = ... compute Details ...
}
return details;
}
}
public class UserDetailsAction {
private static final ObjectWriter writer = new ObjectMapper();
private static final ObjectWriter writerAdmin = writer
.writerWithView(User.AdminView.class);
public String getUserAsJson(User user) {
return writer.writeValueAsString(user);
}
public String getUserAsJsonForAdmin(User user) {
return writerAdmin.writeValueAsString(user);
}
}
如果我调用getUserAsJson,我希望看到id,email和其他字段,但不是详细信息。这很好用。但我看到getUserAsJsonForAdmin也一样,也没有细节。如果我删除@JsonIgnore注释 - 我确实在两个调用中都看到了详细信息。
我错了什么,有好的方法吗?谢谢!
答案 0 :(得分:5)
您可能会发现使用the dynamic Jackson filtering稍微优雅一点的用例。以下是基于共享一个对象映射器实例的自定义注释过滤POJO字段的示例:
public class JacksonFilter {
static private boolean shouldIncludeAllFields;
@Retention(RetentionPolicy.RUNTIME)
public static @interface Admin {}
@JsonFilter("admin-filter")
public static class User {
public final String email;
@Admin
public final String details;
public User(String email, String details) {
this.email = email;
this.details = details;
}
}
public static class AdminPropertyFilter extends SimpleBeanPropertyFilter {
@Override
protected boolean include(BeanPropertyWriter writer) {
// deprecated since 2.3
return true;
}
@Override
protected boolean include(PropertyWriter writer) {
if (writer instanceof BeanPropertyWriter) {
return shouldIncludeAllFields || ((BeanPropertyWriter) writer).getAnnotation(Admin.class) == null;
}
return true;
}
}
public static void main(String[] args) throws JsonProcessingException {
User user = new User("email", "secret");
ObjectMapper mapper = new ObjectMapper();
mapper.setFilters(new SimpleFilterProvider().addFilter("admin-filter", new AdminPropertyFilter()));
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
shouldIncludeAllFields = true;
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
}
}
输出:
{
"email" : "email"
}
{
"email" : "email",
"details" : "secret"
}
答案 1 :(得分:0)
看起来像杰克逊在像@JsonView这样很酷的功能上有一个可怕的概念。我发现解决问题的唯一方法是:
@JsonInclude(Include.NON_NULL)
@Entity
public class User {
public static interface BasicView {}
public static interface AdminView {}
... id and others ...
@JsonView({BasicView.class, AdminView.class}) // And this for EVERY field
@Column
private String email;
@Transient
private transient Details details;
@JsonView(AdminView.class)
public Details getDetails() {
if (details == null) {
details = ... compute Details ...
}
return details;
}
}
public class UserDetailsAction {
private static final ObjectWriter writer = new ObjectMapper()
.disable(MapperFeature.DEFAULT_VIEW_INCLUSION)
.writerWithView(User.BasicView.class);
private static final ObjectWriter writerAdmin = new ObjectMapper()
.disable(MapperFeature.DEFAULT_VIEW_INCLUSION)
.writerWithView(User.AdminView.class);
public String getUserAsJson(User user) {
return writer.writeValueAsString(user);
}
public String getUserAsJsonForAdmin(User user) {
return writerAdmin.writeValueAsString(user);
}
}
也许它帮助了一个人。但我希望找到更好的解决方案,因为我不接受自己的答案。
编辑:因为接口可以扩展(多个)接口,我可以使用:
public static interface AdminView extends BasicView {}
只是
@JsonView(BasicView.class)
而不是
@JsonView({BasicView.class, AdminView.class})