首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何动态忽略Jackson序列化中的属性

如何动态忽略Jackson序列化中的属性
EN

Stack Overflow用户
提问于 2018-07-04 11:22:57
回答 3查看 14.4K关注 0票数 19

我有一个具有多个@ManyToOne关联的实体。我正在使用spring引导来公开REST。目前,我有多个REST,它们返回整个实体的JSON响应,包括关联。

但我不想序列化所有REST中的所有相关对象。

例如

  • API-1应该返回父对象+ associationA对象
  • API-2应该返回父+ associationA + associationB对象。
  • API-3应该返回父+ associationB + associationC + associationD

因此,在我的序列化过程中,除了associationA的API-1之外,我想忽略所有关联。

对于API-2,我想忽略除A和B之外的其他关联。

如何在Jackson序列化期间动态忽略这些属性?

注意:我对每个API都使用相同的类;我不感兴趣为每个API创建一个DTO。

任何建议都会受到国王的赞赏。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-07-04 11:29:07

我把三种在杰克逊中执行动态过滤的方法组合在一起。其中之一必须适合你的需要。

使用@JsonView

您可以使用@JsonView

代码语言:javascript
运行
复制
public class Views {         
    interface Simple { }  
    interface Detailed extends Simple { }   
}
代码语言:javascript
运行
复制
public class Foo {

    @JsonView(Views.Simple.class)
    private String name;

    @JsonView(Views.Detailed.class)
    private String details;

    // Getters and setters
}
代码语言:javascript
运行
复制
@RequestMapping("/foo")
@JsonView(Views.Detailed.class)
public Foo getFoo() {
    Foo foo = new Foo();
    return foo;
}

或者,您可以使用MappingJacksonValue动态设置视图。

代码语言:javascript
运行
复制
@RequestMapping("/foo")
public MappingJacksonValue getFoo() {
    Foo foo = new Foo();
    MappingJacksonValue result = new MappingJacksonValue(foo);
    result.setSerializationView(Views.Detailed.class);
    return result;
}

使用BeanSerializerModifier

您可以扩展BeanSerializerModifier,然后重写changeProperties()方法。它允许您根据需要添加、删除或替换任何用于序列化的属性:

代码语言:javascript
运行
复制
public class CustomSerializerModifier extends BeanSerializerModifier {

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
        BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {

        // In this method you can add, remove or replace any of passed properties

        return beanProperties;
    }
}

然后将序列化程序注册为ObjectMapper中的一个模块。

代码语言:javascript
运行
复制
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule() {

    @Override
    public void setupModule(SetupContext context) {
        super.setupModule(context);
        context.addBeanSerializerModifier(new CustomSerializerModifier());
    }
});

查看示例herehere

@JsonFilterSimpleBeanPropertyFilter结合使用

另一种方法涉及到@JsonFilter

代码语言:javascript
运行
复制
@JsonFilter("customPropertyFilter")
public class Foo {

    private String name;
    private String details;

    // Getters and setters
}

扩展SimpleBeanPropertyFilter并根据需要重写serializeAsField()方法:

代码语言:javascript
运行
复制
public class CustomPropertyFilter extends SimpleBeanPropertyFilter {

    @Override
    public void serializeAsField(Object pojo, JsonGenerator jgen,
                                 SerializerProvider provider, 
                                 PropertyWriter writer) throws Exception {

        // Serialize a field
        // writer.serializeAsField(pojo, jgen, provider, writer);

        // Omit a field from serialization
        // writer.serializeAsOmittedField(pojo, jgen, provider);
    }
}

然后在ObjectMapper中注册过滤器

代码语言:javascript
运行
复制
FilterProvider filterProvider = new SimpleFilterProvider()
        .addFilter("customPropertyFilter", new CustomPropertyFilter());

ObjectMapper mapper = new ObjectMapper();
mapper.setFilterProvider(filterProvider);

如果希望使筛选器“全局”,即应用于所有bean,则可以创建混合类并使用@JsonFilter("customPropertyFilter")对其进行注释。

代码语言:javascript
运行
复制
@JsonFilter("customPropertyFilter")
public class CustomPropertyFilterMixIn {

}

然后将混合类绑定到Object

代码语言:javascript
运行
复制
mapper.addMixIn(Object.class, CustomPropertyFilterMixIn.class);
票数 35
EN

Stack Overflow用户

发布于 2022-01-18 13:54:53

代码语言:javascript
运行
复制
  public static <T> String getNonNullFieldsSerialized(T object, ObjectMapper objectMapper)throws JsonProcessingException {

    Map<String, Object> objectMap = objectMapper.convertValue(object, new TypeReference<Map<String, Object>>() {});

    Map<String, Object> objectMapNonNullValues = objectMap.entrySet().stream()
            .filter(stringObjectEntry -> Objects.nonNull(stringObjectEntry.getValue()))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

    return objectMapper.writeValueAsString(objectMapNonNullValues);
  }

这将基本上忽略所有非空字段。同样,您可以通过更改映射筛选条件来忽略其他字段。

票数 1
EN

Stack Overflow用户

发布于 2021-06-14 02:52:21

我对从db获取数据并使用rest返回数据实现了动态筛选。我避免使用MappingJacksonValue.As,它在对象链接时遇到问题。

代码语言:javascript
运行
复制
@GetMapping("/courses")
    public ResponseEntity<JpaResponse> allCourse() throws Exception {
        JpaResponse response = null;
         ObjectMapper mapper = new ObjectMapper(); 
         mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        List<Course> course = service.findAllCourse();
        SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept("name","reviews");
        FilterProvider filterProvider = new SimpleFilterProvider().addFilter("jpafilter", filter).setFailOnUnknownId(false);
                ObjectWriter writer = mapper.writer(filterProvider);
        String writeValueAsString = writer.writeValueAsString(course);
        List<Course> resultcourse = mapper.readValue(writeValueAsString,List.class);
            response = new JpaResponse(HttpStatus.OK.name(),resultcourse);
            return new ResponseEntity<>(response, HttpStatus.OK);

}

public class JpaResponse {
        private String status;
        private Object data;
        public JpaResponse() {
            super();
        }
        public JpaResponse(String status, Object data) {
            super();
            this.status = status;
            this.data = data;
        }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51172496

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档