如何使用Jackson排除超类属性

huangapple go评论88阅读模式
英文:

How to exclude super class properties using Jackson

问题

我有一个类:

  1. public class User extends Body {
  2. private Integer userId;
  3. private String userName;
  4. private String emailId;
  5. //getters and setters
  6. }

我想要通过Jackson映射器排除Body类的属性,因为我遇到了一个错误。

  1. ObjectMapper mapper = new ObjectMapper();
  2. User user = new User();
  3. String jsonString = mapper.writeValueAsString(user);

我如何将对象转换为JSON,排除所有继承或实现的类?我只需要转换User类,不需要Body类。

我的父类有很多像这样的公共方法:

  1. public final Enumeration method(String email) {
  2. throw new RuntimeException("Error");
  3. }
  4. public final Object method(String name) {
  5. throw new RuntimeException("Error");
  6. }
英文:

I have a class:

  1. public class User extends Body {
  2. private Integer userId;
  3. private String userName;
  4. private String emailId;
  5. //getters and setters
  6. }

I want to exclude Body class properties with Jackson mapper because I get an error.

  1. ObjectMapper mapper = new ObjectMapper();
  2. User user = new User;
  3. 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:

  1. public final Enumeration method(String email) {
  2. throw new RuntimeException("Error");
  3. }
  4. public final Object method(String name) {
  5. throw new RuntimeException("Error");
  6. }

答案1

得分: 4

1. 使用 @JsonView 注解

Jackson 库有一个 @JsonView 注解,它允许提供序列化类的不同视图。

您需要创建一个描述不同视图的类,就像这样:

  1. public class Views {
  2. public interface Base {} // 基类属性的视图
  3. public interface Child {} // 子类属性的视图(如 User)
  4. }

然后,在基类 Body 的字段/获取器上标记 @JsonView(Views.Base.class)

  1. public class Body {
  2. @JsonView(Views.Base.class)
  3. private int foo;
  4. @JsonView(Views.Base.class)
  5. public String getBar() {
  6. return "bar";
  7. }
  8. // 其他获取器/设置器
  9. }

User 类可以在类级别上进行标记:

  1. @JsonView(Views.Child.class)
  2. public class User extends Body {
  3. private Integer userId;
  4. private String userName;
  5. private String email;
  6. // 获取器/设置器
  7. }

当使用 ObjectMapper 进行序列化时,您可以设置其 writer 使用特定视图 writerWithView

  1. ObjectMapper mapper = new ObjectMapper();
  2. User user = new User(1, "Jack", "jack@company.com");
  3. String json = mapper.writerWithView(Views.Child.class).writeValueAsString(user);
  4. System.out.println("自定义视图:" + json);
  5. System.out.println("完整视图:" + mapper.writeValueAsString(user));

输出:

  1. 自定义视图:{"userId":1,"userName":"Jack","email":"jack@company.com"}
  2. 完整视图:{"foo":0,"userId":1,"userName":"Jack","email":"jack@company.com","bar":"bar"}

2. 使用 @JsonIgnoreProperties 注解

还可以通过忽略父类的属性来自定义子类的视图:

  1. @JsonIgnoreProperties({"foo", "bar"})
  2. public class User extends Body {
  3. private Integer userId;
  4. private String userName;
  5. private String email;
  6. }

然后,无需配置 writer 的 ObjectMapper 实例:

  1. System.out.println("忽略基类字段:" + mapper.writeValueAsString(user));

输出:

  1. 忽略基类字段:{"userId":1,"userName":"Jack","email":"jack@company.com"}

3. 配置 ObjectMapper 设置自定义的 JacksonAnnotationIntrospector

还可以配置 ObjectMapper 实例以设置自定义的注解内省器,以完全忽略属于父类 Body 的属性:

  1. // 导入用于 Jackson v.2.x 的类
  2. // import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
  3. // import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
  4. // 导入用于 Jackson v.1.9 的类
  5. import org.codehaus.jackson.map.introspect.AnnotatedMember;
  6. import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;
  7. class IgnoreBodyClassIntrospector extends JacksonAnnotationIntrospector {
  8. @Override
  9. public boolean hasIgnoreMarker(final AnnotatedMember member) {
  10. return member.getDeclaringClass() == Body.class || super.hasIgnoreMarker(member);
  11. }
  12. }

配置 ObjectMapper 并将 User 序列化,无需更改 BodyUser 的任何代码:

  1. ObjectMapper mapper = new ObjectMapper()
  2. .setAnnotationIntrospector(new IgnoreBodyClassIntrospector());
  3. User user = new User(3, "Nobody", "nobody@company.com");
  4. System.out.println("没有基类字段:" + mapper.writeValueAsString(user));

输出:

  1. 没有基类字段:{"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:

  1. public class Views {
  2. public interface Base {} // view of Base class properties
  3. public interface Child {} // view of Child class properties (i.e. User)
  4. }

Then you mark up the fields/getters in the base Body class with @JsonView(Views.Base.class):

  1. public class Body {
  2. @JsonView(Views.Base.class)
  3. private int foo;
  4. @JsonView(Views.Base.class)
  5. public String getBar() {
  6. return "bar";
  7. }
  8. // other getters/setters
  9. }

The User class can be marked at class level:

  1. @JsonView(Views.Child.class)
  2. public class User extends Body {
  3. private Integer userId;
  4. private String userName;
  5. private String email;
  6. // getters/setters
  7. }

And when serializing with ObjectMapper you set its writer up to use specific view writerWithView:

  1. ObjectMapper mapper = new ObjectMapper();//
  2. User user = new User(1, "Jack", "jack@company.com");
  3. String json = mapper.writerWithView(Views.Child.class).writeValueAsString(user);
  4. System.out.println("custom view: " + json);
  5. System.out.println("full view: " + mapper.writeValueAsString(user));

Output:

  1. custom view: {"userId":1,"name":"Jack","email":"jack@company.com"}
  2. 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:

  1. @JsonIgnoreProperties({"foo", "bar"})
  2. public class User extends Body {
  3. private Integer userId;
  4. private String name;
  5. private String email;
  6. }

Then there's no need to configure the writer ObjectMapper instance:

  1. System.out.println("base class fields ignored: " + mapper.writeValueAsString(user));

Output:

  1. 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:

  1. // imports for Jackson v.2.x
  2. // import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
  3. // import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
  4. // imports for Jackson v.1.9
  5. import org.codehaus.jackson.map.introspect.AnnotatedMember;
  6. import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;
  7. class IgnoreBodyClassIntrospector extends JacksonAnnotationIntrospector {
  8. @Override
  9. public boolean hasIgnoreMarker(final AnnotatedMember member) {
  10. return member.getDeclaringClass() == Body.class || super.hasIgnoreMarker(member);
  11. }
  12. }

Configure ObjectMapper and serialize User without any code changes to Body and User:

  1. ObjectMapper mapper = new ObjectMapper()
  2. .setAnnotationIntrospector(new IgnoreBodyClassIntrospector());
  3. User user = new User(3, "Nobody", "nobody@company.com");
  4. System.out.println("no base class fields: " + mapper.writeValueAsString(user));

Output:

  1. no base class fields: {"userId":3,"name":"Nobody","email":"nobody@company.com"}

huangapple
  • 本文由 发表于 2020年9月28日 16:54:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/64098919.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定