【问题标题】:How to exclude super class properties using Jackson如何使用杰克逊排除超类属性
【发布时间】:2020-09-28 08:54:05
【问题描述】:

我有一堂课:

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");
}

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    1.使用@JsonView注解

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

    您需要创建一个描述不同视图的类,如下所示:

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

    然后你用@JsonView(Views.Base.class)标记基类Body中的字段/getter:

    public class Body {
        @JsonView(Views.Base.class)
        private int foo;
    
        @JsonView(Views.Base.class)
        public String getBar() {
            return "bar";
        }
    
        // other getters/setters
    }
    

    User 类可以在类级别标记:

    @JsonView(Views.Child.class)
    public class User extends Body {
        private Integer userId;
        private String userName;
        private String email;
    
        // getters/setters
    }
    

    当使用ObjectMapper 进行序列化时,您将其编写器设置为使用特定视图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));
    

    输出:

    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。使用@JsonIgnoreProperties注解

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

    @JsonIgnoreProperties({"foo", "bar"})
    public class User extends Body {
        private Integer userId;
        private String name;
        private String email;
    }
    

    那么就不用配置作者ObjectMapper实例了:

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

    输出:

    base class fields ignored: {"userId":1,"name":"Jack","email":"jack@company.com"}
    

    3。配置ObjectMapper 设置自定义JacksonAnnotationIntrospector

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

    // 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);
        }
    }
    

    配置ObjectMapper并序列化User,无需对BodyUser进行任何代码更改:

    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));
    

    输出:

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

    【讨论】:

    • 我无法更改 Body 类。 Body 类也不是 POJO,它有很多公共方法
    • @ValdyB,如果Body不是POJO,它如何干扰User序列化?如果Body 包含一些字段/getter,那么您可以将@JsonIgnoreProperties 添加到子类User 中吗?
    • Body 类有 1000 个公共方法,所以 Jacson 正在尝试序列化它并得到错误。我也不能使用@JsonIgnoreProperties,因为我有动态和巨大的 Body 类
    • @ValdyB,我添加了另一个选项,以使用自定义 JacksonAnnotationIntrospector 完全禁用属于超级 Body 类的属性的序列化
    • 您是否尝试在 Jackson v.1.9 中更新导入以引用 org.codehaus.jackson.map.introspect.* 而不是 Jackson v.2.x 中的 com.fasterxml.jackson.databind.introspect.*
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 2023-04-10
    • 2012-08-23
    相关资源
    最近更新 更多