json数据平铺规则

json数据平铺规则

maven依赖

<!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
        </dependency>

工具类

package org.apache.nifi.processor.json;

import net.sf.json.JSONObject;
import org.apache.nifi.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/*
 * @ClassName:JSONTileUtil
 * @Description json数据平铺解析工具类
 * @Author cch
 * @Time 2021/8/9 15:40
 */
public class JSONTileUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(JSONTileUtil.class);

    public static final int ROOT_ONLY = 0;//只获取1级json
    public static final int LEVEL_WITH_ROOT = 1;//获取指定层级json追加到1级
    public static final int LEVEL_ONLY = 2;//只获取指定层级json
    public static final int LEVEL_EACH = 3;//从1级开始逐层追加json,同名的key使用key_n的形式(从2开始)
    public static final int ALL = 4;//平铺所有
    public static final int EXTRACT_KEY = 5;

    public static final String DEFAULT_SPLICING = "_";//默认的父子节key的连接符



    /*
     * @description 根据指定key获取json数据,此方法不具有层级结构特性,只是单纯的获取指定key下的数据
     * @method extractKey
     * @author cch
     * @param key 指定key
     * @param json 源json字符串
     * @time 2021/8/17 15:23
     * @return java.lang.String
     */
    public static String extractKey(String key,int level,String json){
        String tileJson = getTileJson(json, level, LEVEL_ONLY);
        JSONObject jsonObject = JSONObject.fromObject(tileJson);
        Object o = jsonObject.get(key);
        return o==null?"":o.toString();
    }

    /*
     * @description 平铺所有key/value
     * @method tileAll
     * @author cch
     * @param json
     * @time 2021/8/9 18:30
     * @return java.lang.String
     */
    public static String tileAll(String json){
        JSONObject jsonObject = new JSONObject();
        Map<String,Integer> keyMap = new HashMap<>();
        Map<Integer, List<LevelItem>> tileMap = tile(json);
        Set<Map.Entry<Integer, List<LevelItem>>> entries = tileMap.entrySet();
        for (Map.Entry<Integer, List<LevelItem>> entry : entries) {
            List<LevelItem> value = entry.getValue();
            for (LevelItem levelItem : value) {
                if(levelItem instanceof LevelSubItem) continue;
                String key = levelItem.getKey();
                if(keyMap.containsKey(key)){
                    Integer count = keyMap.get(key);
                    count=count+1;
                    keyMap.put(key,count);
                    jsonObject.put(key+DEFAULT_SPLICING+count,levelItem.getValue());
                }else {
                    jsonObject.put(levelItem.getKey(),levelItem.getValue());
                }
            }
        }
        return jsonObject.toString();
    }

    /*
     * @description 只获取嵌套json的1级key/value
     * @method getRootJson
     * @author cch
     * @param json
     * @time 2021/8/9 18:29
     * @return java.lang.String
     */
    public static String getRootJson(String json){
        return getTileJson(json,1,0);
    }

    /*
     * @description 平铺指定层级的json数据,有三个策略可以使用,
     * 0->只获取第一层的json,1->获取指定层级json追加到第一层,2->只获取指定层级的json,3->从1级开始逐层追加json,同名的key使用key_n的形式(从2开始),例如name,name_2,name_3
     * @method getTileJson
     * @author cch
     * @param json
     * @param level
     * @param strategy
     * @time 2021/8/9 16:20
     * @return java.lang.String
     */
    public static String getTileJson(String json,int level,int strategy){
        Map<Integer, List<LevelItem>> tileMap = tile(json);
        if(!tileMap.containsKey(level)){
            LOGGER.warn("指定的level不存在,请重新指定正确的level:");
//            throw new IllegalStateException("指定的level不存在,请重新指定正确的level: " );
            return null;
        }

        JSONObject jsonObject = new JSONObject();
        switch (strategy){
            case ROOT_ONLY:
                for (LevelItem levelItem : tileMap.get(ROOT_ONLY + 1)) {
                    if(levelItem instanceof LevelSubItem) {
                        jsonObject.put(levelItem.getKey(),"\""+levelItem.getValue()+"\"");
                    }else{
                        jsonObject.put(levelItem.getKey(),levelItem.getValue());
                    }
                }
                break;
            case LEVEL_WITH_ROOT:
                //1级
                for (LevelItem levelItem : tileMap.get(ROOT_ONLY + 1)) {
                    if(levelItem instanceof LevelSubItem) continue;
                    jsonObject.put(levelItem.getKey(),levelItem.getValue());
                }
                //指定层级
                for (LevelItem levelItem : tileMap.get(level)) {
                    if(levelItem instanceof LevelSubItem) {
                        jsonObject.put(levelItem.getKey(),"\""+levelItem.getValue()+"\"");
                    }else{
                        jsonObject.put(levelItem.getKey(),levelItem.getValue());
                    }
                }
                break;
            case LEVEL_ONLY:
                for (LevelItem levelItem : tileMap.get(level)) {
                    if(levelItem instanceof LevelSubItem) {
                        jsonObject.put(levelItem.getKey(),"\""+levelItem.getValue()+"\"");
                    }else{
                        jsonObject.put(levelItem.getKey(),levelItem.getValue());
                    }
                }
                break;
            case LEVEL_EACH:
                Map<String,Integer> keyMap = new HashMap<>();
                for(int index=0;index<level;index++){
                    for (LevelItem levelItem : tileMap.get(index+1)) {
                        if(levelItem instanceof LevelSubItem&&(index+1)<level) continue;
                        String key = levelItem.getKey();
                        if(!jsonObject.containsKey(key)){
                            if(levelItem instanceof LevelSubItem) {
                                jsonObject.put(levelItem.getKey(),"\""+levelItem.getValue()+"\"");
                            }else{
                                jsonObject.put(levelItem.getKey(),levelItem.getValue());
                            }
                            keyMap.put(key,1);
                        }else{
                            int n = keyMap.get(key)+1;
                            if(levelItem instanceof LevelSubItem) {
                                jsonObject.put(levelItem.getKey()+"_"+n,"\""+levelItem.getValue()+"\"");
                            }else{
                                jsonObject.put(levelItem.getKey()+"_"+n,levelItem.getValue());
                            }
                            keyMap.put(key,n);
                        }
                    }
                }
                break;
            case ALL:
                return tileAll(json);
        }

        return jsonObject.toString();
    }

    public static String getSplicingTileJson(String json){
        return getSplicingTileJson(json,DEFAULT_SPLICING);
    }



    /*
     * @description 连接符模式的所有key value平铺
     * @method getSplicingTileJson
     * @author cch
     * @param json
     * @param splicing
     * @time 2021/8/9 18:57
     * @return java.lang.String
     */
    public static String getSplicingTileJson(String json,String splicing){
        if(splicing==null){
            throw new RuntimeException("连接符不能为空");
        }

        splicing = splicing.trim();
        if(splicing.equals("")){
            throw new RuntimeException("连接符不能是空格符号");
        }

        JSONObject jsonObject = new JSONObject(false);
        Map<String,Integer> keyMap = new HashMap<>();
        Map<Integer, List<LevelItem>> tileMap = tile(json);
        Set<Map.Entry<Integer, List<LevelItem>>> entries = tileMap.entrySet();
        for (Map.Entry<Integer, List<LevelItem>> entry : entries) {
            List<LevelItem> value = entry.getValue();
            for (LevelItem levelItem : value) {
                if(levelItem instanceof LevelSubItem) continue;
                String path = levelItem.getPath();
                if(!StringUtils.isEmpty(path)){
                    path = path.replace(DEFAULT_SPLICING,splicing);
                }else{
                    path = levelItem.getKey();
                }
                if(!jsonObject.containsKey(path)){
                    jsonObject.put(path,levelItem.getValue());
                    keyMap.put(path,1);
                }else{
                    int n = keyMap.get(path)+1;
                    jsonObject.put(path+"_"+n,levelItem.getValue());
                    keyMap.put(path,n);
                }
            }
        }
        return jsonObject.toString();
    }


    public static String getSplicingTileJson(String json,int level,int strategy){
        return getSplicingTileJson(json,level,strategy,DEFAULT_SPLICING);
    }

    /*
     * @description 使用连接符的方式平铺指定层级的json数据,有三个策略可以使用,
     * 0->只获取第一层的json,1->获取指定层级json追加到第一层,2->只获取指定层级的json,3->从1级开始逐层追加json,同名的key使用key_n的形式(从2开始),例如name,name_2,name_3
     * @method getSplicingTileJson
     * @author cch
     * @param json
     * @param level
     * @param strategy
     * @param splicing
     * @time 2021/8/9 16:36
     * @return java.lang.String
     */
    public static String getSplicingTileJson(String json,int level,int strategy,String splicing){

        Map<Integer, List<LevelItem>> tileMap = tile(json);
        if(!tileMap.containsKey(level)){
//            throw new IllegalStateException("指定的level不存在,请重新指定正确的level:" );
            LOGGER.warn("指定的level不存在,请重新指定正确的level:");
            return null;
        }

        JSONObject jsonObject = new JSONObject();
        switch (strategy){
            case ROOT_ONLY:
                for (LevelItem levelItem : tileMap.get(ROOT_ONLY + 1)) {
                    if(levelItem instanceof LevelSubItem) {
                        jsonObject.put(levelItem.getKey(),"\""+levelItem.getValue()+"\"");
                    }else{
                        jsonObject.put(levelItem.getKey(),levelItem.getValue());
                    }
                }
                break;
            case LEVEL_WITH_ROOT:
                for (LevelItem levelItem : tileMap.get(ROOT_ONLY + 1)) {
                    if(levelItem instanceof LevelSubItem) continue;
                    jsonObject.put(levelItem.getKey(),levelItem.getValue());
                }

                for (LevelItem levelItem : tileMap.get(level)) {
                    StringBuilder keyBuilder = new StringBuilder();
                    keyBuilder.append(levelItem.getParentKey()).append(splicing).append(levelItem.getKey());

                    if(levelItem instanceof LevelSubItem) {
                        jsonObject.put(keyBuilder.toString(),"\""+levelItem.getValue()+"\"");
                    }else{
                        jsonObject.put(keyBuilder.toString(),levelItem.getValue());
                    }
                }
                break;
            case LEVEL_ONLY:
                for (LevelItem levelItem : tileMap.get(level)) {
                    if(levelItem instanceof LevelSubItem) {
                        jsonObject.put(levelItem.getKey(),"\""+levelItem.getValue()+"\"");
                    }else{
                        jsonObject.put(levelItem.getKey(),levelItem.getValue());
                    }
                }
                break;
            case LEVEL_EACH:
                Map<String,Integer> keyMap = new HashMap<>();
                for(int index=0;index<level;index++){
                    for (LevelItem levelItem : tileMap.get(index+1)) {
                        if(levelItem instanceof LevelSubItem&&(index+1)<level) continue;
                        String path = levelItem.getPath();
                        if(!StringUtils.isEmpty(path)){
                            path = path.replace(DEFAULT_SPLICING,splicing);
                        }else{
                            path = levelItem.getKey();
                        }
                        if(!jsonObject.containsKey(path)){
                            if(levelItem instanceof LevelSubItem) {
                                jsonObject.put(path,"\""+levelItem.getValue()+"\"");
                            }else{
                                jsonObject.put(path,levelItem.getValue());
                            }
                            keyMap.put(path,1);
                        }else{
                            int n = keyMap.get(path)+1;
                            if(levelItem instanceof LevelSubItem) {
                                jsonObject.put(path+DEFAULT_SPLICING+n,"\""+levelItem.getValue()+"\"");
                            }else{
                                jsonObject.put(path+DEFAULT_SPLICING+n,levelItem.getValue());
                            }
                            keyMap.put(path,n);
                        }
                    }
                }
                break;
            case ALL:
                return getSplicingTileJson(json,splicing);
        }

        return jsonObject.toString();

    }






    private static Map<Integer, List<LevelItem>> tile(String json) {
        if(StringUtils.isEmpty(json)){
            throw new RuntimeException("源JSON为空");
        }

        JSONObject jsonObject = JSONObject.fromObject(json);
        //用来存储层级的map
        Map<Integer, List<LevelItem>> map = new LinkedHashMap<>();

        //默认为1级
        int level = 1;

        //遍历所有的key
        Set<String> keySet = jsonObject.keySet();
        for (String key : keySet) {
            List<LevelItem> levelItems = map.get(level);
            if(levelItems==null){
                levelItems = new ArrayList<>();
                map.put(level,levelItems);
            }

            Object o = jsonObject.get(key);
            //如果某个json值是json对象,则进行递归处理
            if(o instanceof JSONObject){
                JSONObject children = (JSONObject) o;
                //如果是空子对象,则忽略
                if(children.size()==0) continue;
                tile(key,children,level,map,key);
                levelItems.add(new LevelSubItem(key,children.toString(),level));
            }else{
                //如果是正常的值,则写入当前层级
                levelItems.add(new LevelSimpleItem(key,o,level));
            }
        }
        return map;
    }


    private static void tile(String parentKey, JSONObject jsonObject, int level, Map<Integer, List<LevelItem>> map, String path) {
        level++;
        Set<String> keySet = jsonObject.keySet();
        for (String key : keySet) {
            List<LevelItem> levelItems = map.get(level);
            if(levelItems==null){
                levelItems = new ArrayList<>();
                map.put(level,levelItems);
            }
            Object o = jsonObject.get(key);
            if(o instanceof JSONObject){
                JSONObject children = (JSONObject) o;
                String newPath = path+DEFAULT_SPLICING+key;
                //如果是空子对象,则忽略
                if(children.size()==0) continue;
                tile(key,children,level,map,newPath);
                LevelItem levelItem = new LevelSubItem(key,parentKey,children.toString(),level);
                levelItems.add(levelItem);
                levelItem.setPath(newPath);
            }else{
                String newPath = path+DEFAULT_SPLICING+key;
                LevelItem levelItem = new LevelSimpleItem(key,parentKey,o,level);
                levelItem.setPath(newPath);
                levelItems.add(levelItem);
            }
        }
    }
}

json节点接口类

package org.apache.nifi.processor.json;

/*
 * @ClassName:com.cch.test.json.LevelItem
 * @Description 每个层级中每个json的键值对对象
 * @Author cch
 * @Time 2021/8/9 15:03
 */
interface LevelItem {

    String getPath() ;

    void setPath(String path) ;

    String getKey();

    void setKey(String key);

    String getParentKey();

    void setParentKey(String parentKey);

    Object getValue();

    void setValue(Object value);

    int getLevel();

    void setLevel(int level);
}

json节点实现类-无子节点类

package org.apache.nifi.processor.json;

/*
 * @ClassName:org.apache.nifi.processor.json.LevelSimpleItem
 * @Description
 * @Author cch
 * @Time 2021/8/12 20:38
 */
public class LevelSimpleItem implements LevelItem{

    private String key;
    private String parentKey;
    private Object value;
    private int level;
    private String path;

    public LevelSimpleItem(String key, String parentKey, Object value, int level) {
        this.key = key;
        this.parentKey = parentKey;
        this.value = value;
        this.level = level;
    }

    public LevelSimpleItem(String key, Object value, int level) {
        this.key = key;
        this.value = value;
        this.level = level;
    }

    @Override
    public String getKey() {
        return key;
    }

    @Override
    public void setKey(String key) {
        this.key = key;
    }

    @Override
    public String getParentKey() {
        return parentKey;
    }

    @Override
    public void setParentKey(String parentKey) {
        this.parentKey = parentKey;
    }

    @Override
    public Object getValue() {
        return value;
    }

    @Override
    public void setValue(Object value) {
        this.value = value;
    }

    @Override
    public int getLevel() {
        return level;
    }

    @Override
    public void setLevel(int level) {
        this.level = level;
    }

    @Override
    public String getPath() {
        return path;
    }

    @Override
    public void setPath(String path) {
        this.path = path;
    }
}

json节点类-有子节点

package org.apache.nifi.processor.json;

/*
 * @ClassName:org.apache.nifi.processor.json.LevelSubItem
 * @Description
 * @Author cch
 * @Time 2021/8/12 20:49
 */
public class LevelSubItem implements LevelItem{

    private String key;
    private String parentKey;
    private Object value;
    private int level;
    private String path;

    public LevelSubItem(String key, String parentKey, Object value, int level) {
        this.key = key;
        this.parentKey = parentKey;
        this.value = value;
        this.level = level;
    }

    public LevelSubItem(String key, Object value, int level) {
        this.key = key;
        this.value = value;
        this.level = level;
    }

    @Override
    public String getKey() {
        return key;
    }

    @Override
    public void setKey(String key) {
        this.key = key;
    }

    @Override
    public String getParentKey() {
        return parentKey;
    }

    @Override
    public void setParentKey(String parentKey) {
        this.parentKey = parentKey;
    }

    @Override
    public Object getValue() {
        return value;
    }

    @Override
    public void setValue(Object value) {
        this.value = value;
    }

    @Override
    public int getLevel() {
        return level;
    }

    @Override
    public void setLevel(int level) {
        this.level = level;
    }

    @Override
    public String getPath() {
        return path;
    }

    @Override
    public void setPath(String path) {
        this.path = path;
    }
}

样例数据

 
{
    "1a": "1a value",
    "1b": "1b value",
    "1c": {
        "2a": "2a value",
        "2b": "2b value",
        "2c": {
            "3a": "3a value",
            "3b": "3b value",
            "3c": {
                "4a": "4a value",
                "4b": "4b value",
                "4c": {}
            }
        }
    }
}

无连接符模式

  • 只获取1级数据(ROOT_ONLY)
{
    "1a": "1a value",
    "1b": "1b value",
    "1c": "{\"2a\":\"2a value\",\"2b\":\"2b value\",\"2c\":{\"3a\":\"3a
value\",\"3b\":\"3b value\",\"3c\":{\"4a\":\"4a value\",\"4b\":\"4b
value\",\"4c\":{\"5a\":\"5a value\",\"5b\":\"5b value\",\"5c\":{\"6a\":\"6a
value\"}}}}}"
}
  • 追加指定层级到1级(LEVEL_WITH_ROOT)
{
    "1a": "1a value",
    "2b": "2b value",
    "1b": "1b value",
    "2c": "{\"3a\":\"3a value\",\"3b\":\"3b value\",\"3c\":{\"4a\":\"4a
value\",\"4b\":\"4b value\",\"4c\":{\"5a\":\"5a value\",\"5b\":\"5b
value\",\"5c\":{\"6a\":\"6a value\"}}}}",
    "2a": "2a value"
}
  • 3级json追加到1级
{
    "1a": "1a value",
    "3c": "{\"4a\":\"4a value\",\"4b\":\"4b value\",\"4c\":{\"5a\":\"5a
value\",\"5b\":\"5b value\",\"5c\":{\"6a\":\"6a value\"}}}",
    "1b": "1b value",
    "3a": "3a value",
    "3b": "3b value"
}
  • 只获取指定层级(LEVEL_ONLY)(3级)
{
    "3c": "{\"4a\":\"4a value\",\"4b\":\"4b value\",\"4c\":{\"5a\":\"5a
value\",\"5b\":\"5b value\",\"5c\":{\"6a\":\"6a value\"}}}",
    "3a": "3a value",
    "3b": "3b value"
}
  • 从1级开始获取(递归)到指定层级(LEVEL_EACH)(3级)
{
    "1a": "1a value",
    "2b": "2b value",
    "3c": "{\"4a\":\"4a value\",\"4b\":\"4b value\",\"4c\":{\"5a\":\"5a
value\",\"5b\":\"5b value\",\"5c\":{\"6a\":\"6a value\"}}}",
    "1b": "1b value",
    "3a": "3a value",
    "2a": "2a value",
    "3b": "3b value"
}
  • 获取所有有级别数据并铺平
{
    "1a": "1a value",
    "1b": "1b value",
    "2a": "2a value",
    "2b": "2b value",
    "3a": "3a value",
    "3b": "3b value",
    "4a": "4a value",
    "4b": "4b value",
    "5a": "5a value",
    "5b": "5b value",
    "6a": "6a value"
}
  • 获取指定key下的数据,获取第3层级下key为3c的数据
{
    "4a": "4a value",
    "4b": "4b value",
    "4c": {
        "5a": "5a value",
        "5b": "5b value",
        "5c": {
            "6a": "6a value"
        }
    }
}

指定连接符模式 (默认连接符为 _ )

  • 只获取第一级json数据(ROOT_ONLY)
{
    "1a": "1a value",
    "1b": "1b value",
    "1c": "{\"2a\":\"2a value\",\"2b\":\"2b value\",\"2c\":{\"3a\":\"3a
value\",\"3b\":\"3b value\",\"3c\":{\"4a\":\"4a value\",\"4b\":\"4b
value\",\"4c\":{\"5a\":\"5a value\",\"5b\":\"5b value\",\"5c\":{\"6a\":\"6a
value\"}}}}}"
}
  • 指定层级json追加到第一层(LEVEL_WITH_ROOT)
{
    "1a": "1a value",
    "1b": "1b value",
    "1c_2a": "2a value",
    "1c_2b": "2b value",
    "1c_2c": "{\"3a\":\"3a value\",\"3b\":\"3b value\",\"3c\":{\"4a\":\"4a
value\",\"4b\":\"4b value\",\"4c\":{\"5a\":\"5a value\",\"5b\":\"5b
value\",\"5c\":{\"6a\":\"6a value\"}}}}"
}
  • 只获取指定层级json(LEVEL_ONLY)
{
    "2a": "2a value",
    "2b": "2b value",
    "2c": "{\"3a\":\"3a value\",\"3b\":\"3b value\",\"3c\":{\"4a\":\"4a
value\",\"4b\":\"4b value\",\"4c\":{\"5a\":\"5a value\",\"5b\":\"5b
value\",\"5c\":{\"6a\":\"6a value\"}}}}"
}
  • 从1级开始获取(递归)到指定层级(LEVEL_EACH)
{
    "1a": "1a value",
    "1b": "1b value",
    "1c_2a": "2a value",
    "1c_2b": "2b value",
    "1c_2c_3a": "3a value",
    "1c_2c_3b": "3b value",
    "1c_2c_3c": "{\"4a\":\"4a value\",\"4b\":\"4b value\",\"4c\":{\"5a\":\"5a
value\",\"5b\":\"5b value\",\"5c\":{\"6a\":\"6a value\"}}}"
}
  • 获取所有层级json
{
    "1a": "1a value",
    "1b": "1b value",
    "1c_2a": "2a value",
    "1c_2b": "2b value",
    "1c_2c_3a": "3a value",
    "1c_2c_3b": "3b value",
    "1c_2c_3c_4a": "4a value",
    "1c_2c_3c_4b": "4b value",
    "1c_2c_3c_4c_5a": "5a value",
    "1c_2c_3c_4c_5b": "5b value",
    "1c_2c_3c_4c_5c_6a": "6a value"
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值