使用带有Jackson的过滤器将树结构序列化为JSON

时间:2018-10-09 13:33:53

标签: java spring jackson

我有一个formData,它返回以下树结构:

RestController

根据输入参数,我想隐藏@Data public class TreeNode { private String description; private boolean enabled; private Set<TreeNode> children; } enabled的树的节点,并且我正在寻找不需要重建整个树的解决方案。

我在扩展false并添加该规则方面取得了一些成功,但是在控制器中有多个JsonSerializer(一个带有序列化器,一个不带序列化器)并选择一个在参数上。 有没有更简单的方法可以做到这一点?

1 个答案:

答案 0 :(得分:0)

什么回合呢?您从根开始,查找所有子级,如果禁用则将其删除。如果启用,则递归调用相同的trim方法。

您不是要重建树,而是要剪掉不需要的叶子:

// Example for this tree:
//          l0
//     l1        l2
//  l11  l12   l21 l22


TreeNode l11 = new TreeNode("leaf 11", true, Collections.emptySet());
TreeNode l12 = new TreeNode("leaf 12", false, Collections.emptySet());
TreeNode l21 = new TreeNode("leaf 21", true, Collections.emptySet());
TreeNode l22 = new TreeNode("leaf 22", true, Collections.emptySet());
TreeNode l1 = new TreeNode("leaf 1", true, new HashSet<>(Arrays.asList(l11, l12)));
TreeNode l2 = new TreeNode("leaf 2", false, new HashSet<>(Arrays.asList(l21, l22)));
TreeNode l0 = new TreeNode("leaf 0", true, new HashSet<>(Arrays.asList(l1, l2)));



@RequestMapping(value="/api/v1/tree", method = RequestMethod.GET)
public TreeNode getTree(@RequestParam("full") int full){
    System.out.println("getTree full: "+full);

    if(full != 1) {
        trim(l0);
    }

    return l0;
}

private void trim(TreeNode treeNode) {
    for(TreeNode tn : treeNode.getChildren()) {
        if(!tn.isEnabled()) {
            treeNode.getChildren().remove(tn);
        } else {
            trim(tn);
        }
    }
}

编辑

您可以使用PropertyFilter来实现

创建仅允许启用节点的过滤器:

class EnabledTreeNodeFilter extends SimpleBeanPropertyFilter {

    @Override
    public void serializeAsField(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider, PropertyWriter propertyWriter) throws Exception {
        if(((TreeNode) o).isEnabled()) {
            propertyWriter.serializeAsField(o, jsonGenerator, serializerProvider);
        }
    }
}

为您的班级设置过滤器名称

@JsonFilter("enabledTreeNodeFilter")
class TreeNode {
    private String description;
    private boolean enabled;
    private Set<TreeNode> children;

    // Getters
}

将过滤器添加到映射器

ObjectMapper mapper = new ObjectMapper();

// Add this bit in an if, if you want to filter or not
SimpleFilterProvider filters = new SimpleFilterProvider();
filters.addFilter("enabledTreeNodeFilter", new EnabledTreeNodeFilter());
mapper.setFilters(filters);

// Then you can use your mapper
String treeNodeAsString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(l0);
System.out.println(treeNodeAsString);

输出

{
    "description" : "leaf 0",
    "enabled" : true,
    "children" : [ {
        "description" : "leaf 1",
        "enabled" : true,
        "children" : [ {
            "description" : "leaf 11",
            "enabled" : true,
            "children" : [ ]
        }, { } ]
    }, { } ]
}

几乎可以正常工作,我不确定如何清除子数组中的空对象。