如何使用jackson过滤器从java类的列表字段中排除对象

时间:2018-03-06 18:11:01

标签: java json jackson

我正在尝试使用jackson在java中生成一个json对象,我需要从json中的一个字段中过滤掉一些对象。我有一个以下类,我试图转换为json

@JsonIgnoreProperties( {"done", "parent" })
public class Node {
    private String start;
    private String end;
    private int done;
    private Node parent;
    private List<Node> children;

    public Node (String start, String end){
        this.start = start;
        this.end = end;
        this.children = new ArrayList<>();
        this.done=0;
    }
    // getters and setters
}

这里的过滤条件是done == 1 then do not include that node in the list of children。例如,如果我有以下数据结构

obj1: start="1", end="1", done=0, parent=null, children=[obj2, obj3] 
obj2: start="2", end="2", done=1, parent=obj1, children=[] 
obj3: start="3", end="3", done=0, parent=obj1, children=[]

所以最后的json应该看起来像

{start:"1", end:"1", children:[{start:"3", end:"3", children:[]}]} 

而不是

{start:"1", end:"1", children:[{start:"2", end:"2", children:[]}, {start:"3", end:"3", children:[]}]}

我知道杰克逊的基本过滤是如何工作的,所以我做了以下

public void formJson(Node node) {
    ObjectMapper mapper = new ObjectMapper();

    PropertyFilter filter = new SimpleBeanPropertyFilter() {
        @Override
        public void serializeAsField
                (Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
                throws Exception {
            if (include(writer)) {
                int done = ((Node) pojo).getDone();
                if (done == 1) {
                    writer.serializeAsOmittedField(null, jgen, provider);
                }
                else{
                    writer.serializeAsField(pojo, jgen, provider);
                }
            }
        }
        @Override
        protected boolean include(BeanPropertyWriter writer) {
            return true;
        }
        @Override
        protected boolean include(PropertyWriter writer) {
            return true;
        }
    };

    FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter", filter);
    try {
        String jsonInString = mapper.writer(filters).writeValueAsString(node);
        System.out.println(jsonInString);
    } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
}

我理解,如果我想完全排除该字段,上述方法会很好,但这里不一定要排除任何字段,只是根据条件更新该字段。所以这不能实现我想做的事情,如果我将obj2传递给obj1方法,它总是在最终的json中包含formJson。我认为内部杰克逊必须处理子列表中的每个节点,它会将过滤逻辑应用于列表中的每个节点,如果它这样做,它应该从具有done字段为1的子节点中排除节点也许我在这里遗漏了一些东西,对此有任何帮助表示赞赏,谢谢。

1 个答案:

答案 0 :(得分:0)

因此,为了解决这个问题,我最终决定不使用jackson,只使用字符串生成器生成json。

这就是我形成json的方式

private void formJson(Node node, StringBuilder sb) {
        sb.append("{\"start\": \"");
        sb.append(node.getStart());
        sb.append("\", \"end\": ");
        sb.append(node.getEnd());

        sb.append(", \"children\": [");
        for (Node n: node.getChildrens()){
            if(n.getDone()==1){
                continue;
            }
            formJson(n, sb);
            sb.append(",");
        }
        if (sb.charAt(sb.length()-1)==','){
            sb.deleteCharAt(sb.length()-1);
        }
        sb.append("]");
        sb.append("}");
    }