设为首页 加入收藏

TOP

JSON多层嵌套复杂结构数据扁平化处理转为行列数据(一)
2023-07-25 21:34:24 】 浏览:41
Tags:JSON 平化处

背景

公司的中台产品,需要对外部API接口返回的JSON数据进行采集入湖,有时候外部API接口返回的JSON数据层级嵌套比较深,举个栗子:

 

 

 上述的JSON数据中,最外层为请求返回对象,data里面包含返回的业务数据,业务数据按照学校 / 班级 / 学生进行嵌套

在数据入湖时,需要按照最内层的学生视角将数据拆分为行列数据,最终的拆分结果如下:

 

 

由于对接的外部API接口返回的JSON数据结构不是统一的、固定的,所以需要通过一种算法对每一层对象、数组进行遍历和钻取,实现JSON数据的扁平化

网上找了一些JSON扁平化的中间件,例如:Json2Flat在扁平化处理过程不太完美,不支持跨层级的数组嵌套结构

所以决定自己实现扁平化处理

关键代码如下:

public class LinkedNode {

    private LinkedNode parent;

    private String parentName;

    private Map<String, Object> data;

    public LinkedNode(LinkedNode parent, String parentName, Map<String, Object> data) {
        this.parent = parent;
        this.parentName = parentName;
        this.data = data;
    }
}
public class JSONFlatProcessor {

    private LinkedList<LinkedNode> nodes;

    private LinkedList<String> column;

    private List<Object[]> data;

    public void find(LinkedNode parent, String parentName, Map<String, Object> data) {
        LinkedNode node = new LinkedNode(parent, parentName, data);
        if (!hasObjectOrArray(data)) {
            nodes.add(node);
        } else {
            for (Map.Entry entry : data.entrySet()) {
                if (entry.getValue() instanceof Map) {
                    find(node, String.valueOf(entry.getKey()), (Map<String, Object>) entry.getValue());
                } else if (isObjectArray(entry.getValue())) {
                    find(node, String.valueOf(entry.getKey()), (List<Map<String, Object>>) entry.getValue());
                }
            }
        }
    }

    public void find(LinkedNode parent, String parentName, List<Map<String, Object>> data) {
        for (Map<String, Object> item : data) {
            find(parent, parentName, item);
        }
    }

    protected Boolean hasObjectOrArray(Map<String, Object> item) {
        Object field;
        for (Map.Entry entry : item.entrySet()) {
            field = entry.getValue();
            if (field instanceof Map || isObjectArray(field)) {
                return Boolean.TRUE;
            }
        }

        return Boolean.FALSE;
    }

    protected Boolean isObjectArray(Object object) {
        return object instanceof List
                && !CollectionUtils.isEmpty((List) object)
                && ((List) object).get(0) instanceof Map;
    }

    public JSONFlatProcessor process(List<Map<String, Object>> data) {
        nodes = new LinkedList<>();
        find(null, null, data);
        return this;
    }

    public JSONFlatProcessor process(Map<String, Object> data) {
        nodes = new LinkedList<>();
        find(null, null, data);
        return this;
    }

    public LinkedList<LinkedNode> getNodes() {
        return nodes;
    }

    public List<String> getColumn() {

        if (CollectionUtils.isEmpty(nodes)) {
            return Collections.emptyList();
        }

        column = new LinkedList<>();
        collectColumn(nodes.getFirst());

        return column;

    }

    protected void collectColumn(LinkedNode node) {
        List<String> innerColumn = new ArrayList<>(node.getData().size());
        String columnBuilder;
        for (Map.Entry entry : node.getData().entrySet()) {
            if (!(entry.getValue() instanceof Map || isObjectArray(entry.getValue()))) {
                columnBuilder = null == node.getParentName()? String.valueOf(entry.getKey()) : String.format("%s.%s", node.getParentName(), entry.getKey());
                innerColumn.add(columnBuilder);
            }
        }
        column.addAll(0, innerColumn);

        if (null != node.getParent()) {
            collectColumn(node.getParent());
        }
    }

    public List<Object[]> getData() {

        if (CollectionUtils.isEmpty(nodes)) {
            return Collections.emptyList();
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇你还在手写 join 联表查询?MyBat.. 下一篇JVM运行数据区深度解析

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目