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": {}
}
}
}
}
无连接符模式
{
"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"
}
{
"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"
}
{
"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"
}
}
}
指定连接符模式 (默认连接符为 _ )
{
"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\"}}}}"
}
{
"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\"}}}"
}
{
"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"
}