英文:
How to exclude super class properties using Jackson
问题
我有一个类:
public class User extends Body {
private Integer userId;
private String userName;
private String emailId;
//getters and setters
}
我想要通过Jackson映射器排除Body
类的属性,因为我遇到了一个错误。
ObjectMapper mapper = new ObjectMapper();
User user = new User();
String jsonString = mapper.writeValueAsString(user);
我如何将对象转换为JSON,排除所有继承或实现的类?我只需要转换User
类,不需要Body
类。
我的父类有很多像这样的公共方法:
public final Enumeration method(String email) {
throw new RuntimeException("Error");
}
public final Object method(String name) {
throw new RuntimeException("Error");
}
英文:
I have a class:
public class User extends Body {
private Integer userId;
private String userName;
private String emailId;
//getters and setters
}
I want to exclude Body
class properties with Jackson mapper because I get an error.
ObjectMapper mapper = new ObjectMapper();
User user = new User;
String jsonString = mapper.writeValueAsString(user);
How I can convert object to JSON with excluding all extended or implementation class? I need convert only User
class without Body
My super class has many public method like this:
public final Enumeration method(String email) {
throw new RuntimeException("Error");
}
public final Object method(String name) {
throw new RuntimeException("Error");
}
答案1
得分: 4
1. 使用 @JsonView
注解
Jackson 库有一个 @JsonView
注解,它允许提供序列化类的不同视图。
您需要创建一个描述不同视图的类,就像这样:
public class Views {
public interface Base {} // 基类属性的视图
public interface Child {} // 子类属性的视图(如 User)
}
然后,在基类 Body
的字段/获取器上标记 @JsonView(Views.Base.class)
:
public class Body {
@JsonView(Views.Base.class)
private int foo;
@JsonView(Views.Base.class)
public String getBar() {
return "bar";
}
// 其他获取器/设置器
}
User
类可以在类级别上进行标记:
@JsonView(Views.Child.class)
public class User extends Body {
private Integer userId;
private String userName;
private String email;
// 获取器/设置器
}
当使用 ObjectMapper
进行序列化时,您可以设置其 writer 使用特定视图 writerWithView
:
ObjectMapper mapper = new ObjectMapper();
User user = new User(1, "Jack", "jack@company.com");
String json = mapper.writerWithView(Views.Child.class).writeValueAsString(user);
System.out.println("自定义视图:" + json);
System.out.println("完整视图:" + mapper.writeValueAsString(user));
输出:
自定义视图:{"userId":1,"userName":"Jack","email":"jack@company.com"}
完整视图:{"foo":0,"userId":1,"userName":"Jack","email":"jack@company.com","bar":"bar"}
2. 使用 @JsonIgnoreProperties
注解
还可以通过忽略父类的属性来自定义子类的视图:
@JsonIgnoreProperties({"foo", "bar"})
public class User extends Body {
private Integer userId;
private String userName;
private String email;
}
然后,无需配置 writer 的 ObjectMapper
实例:
System.out.println("忽略基类字段:" + mapper.writeValueAsString(user));
输出:
忽略基类字段:{"userId":1,"userName":"Jack","email":"jack@company.com"}
3. 配置 ObjectMapper
设置自定义的 JacksonAnnotationIntrospector
还可以配置 ObjectMapper
实例以设置自定义的注解内省器,以完全忽略属于父类 Body
的属性:
// 导入用于 Jackson v.2.x 的类
// import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
// import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
// 导入用于 Jackson v.1.9 的类
import org.codehaus.jackson.map.introspect.AnnotatedMember;
import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;
class IgnoreBodyClassIntrospector extends JacksonAnnotationIntrospector {
@Override
public boolean hasIgnoreMarker(final AnnotatedMember member) {
return member.getDeclaringClass() == Body.class || super.hasIgnoreMarker(member);
}
}
配置 ObjectMapper
并将 User
序列化,无需更改 Body
和 User
的任何代码:
ObjectMapper mapper = new ObjectMapper()
.setAnnotationIntrospector(new IgnoreBodyClassIntrospector());
User user = new User(3, "Nobody", "nobody@company.com");
System.out.println("没有基类字段:" + mapper.writeValueAsString(user));
输出:
没有基类字段:{"userId":3,"userName":"Nobody","email":"nobody@company.com"}
英文:
1. Using @JsonView
annotation
Jackson library has @JsonView
annotation which allows to provide different views of the serialized class.
You need to create a class describing different views like this:
public class Views {
public interface Base {} // view of Base class properties
public interface Child {} // view of Child class properties (i.e. User)
}
Then you mark up the fields/getters in the base Body
class with @JsonView(Views.Base.class)
:
public class Body {
@JsonView(Views.Base.class)
private int foo;
@JsonView(Views.Base.class)
public String getBar() {
return "bar";
}
// other getters/setters
}
The User
class can be marked at class level:
@JsonView(Views.Child.class)
public class User extends Body {
private Integer userId;
private String userName;
private String email;
// getters/setters
}
And when serializing with ObjectMapper
you set its writer up to use specific view writerWithView
:
ObjectMapper mapper = new ObjectMapper();//
User user = new User(1, "Jack", "jack@company.com");
String json = mapper.writerWithView(Views.Child.class).writeValueAsString(user);
System.out.println("custom view: " + json);
System.out.println("full view: " + mapper.writeValueAsString(user));
Output:
custom view: {"userId":1,"name":"Jack","email":"jack@company.com"}
full view: {"foo":0,"userId":1,"name":"Jack","email":"jack@company.com","bar":"bar"}
2. Using @JsonIgnoreProperties
annotation
It is also possible to customize the view of the child class by ignoring its parent class' properties:
@JsonIgnoreProperties({"foo", "bar"})
public class User extends Body {
private Integer userId;
private String name;
private String email;
}
Then there's no need to configure the writer ObjectMapper
instance:
System.out.println("base class fields ignored: " + mapper.writeValueAsString(user));
Output:
base class fields ignored: {"userId":1,"name":"Jack","email":"jack@company.com"}
3. Configure ObjectMapper
to set custom JacksonAnnotationIntrospector
It is also possible to configure the ObjectMapper
instance to set a custom annotation introspector to completely ignore properties belonging to the parent Body
class:
// imports for Jackson v.2.x
// import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
// import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
// imports for Jackson v.1.9
import org.codehaus.jackson.map.introspect.AnnotatedMember;
import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;
class IgnoreBodyClassIntrospector extends JacksonAnnotationIntrospector {
@Override
public boolean hasIgnoreMarker(final AnnotatedMember member) {
return member.getDeclaringClass() == Body.class || super.hasIgnoreMarker(member);
}
}
Configure ObjectMapper
and serialize User
without any code changes to Body
and User
:
ObjectMapper mapper = new ObjectMapper()
.setAnnotationIntrospector(new IgnoreBodyClassIntrospector());
User user = new User(3, "Nobody", "nobody@company.com");
System.out.println("no base class fields: " + mapper.writeValueAsString(user));
Output:
no base class fields: {"userId":3,"name":"Nobody","email":"nobody@company.com"}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论