准备工作:json字符串

[{
"id": 1,
"code": "FLOW_NODE_1",
"name": "环节A",
"children": [{
"id": 2,
"code": "RULE_NODE_1",
"name": "规则A"
}, {
"id": 3,
"code": "RULE_NODE_2",
"name": "规则B"
}, {
"id": 4,
"code": "PARALLEL_NODE_2",
"name": "并行节点",
"children": [{
"id": 5,
"code": "RULE_NODE_3",
"name": "规则C1"
}, {
"id": 6,
"code": "RULE_COLLECTION_1",
"name": "规则集1",
"children": [{
"id": 7,
"code": "RULE_NODE_4",
"name": "规则C21"
}, {
"id": 8,
"code": "RULE_NODE_5",
"name": "规则C22"
}]
}]
}, {
"id": 9,
"code": "MUTUAL_NODE_1",
"name": "互斥节点",
"children": [{
"id": 10,
"code": "RULE_NODE_6",
"name": "规则D1"
}, {
"id": 11,
"code": "RULE_NODE_7",
"name": "规则D2"
}]
}]
}, {
"id": 12,
"code": "FLOW_NODE_2",
"name": "环节B" }]

这里使用的springboot下FastJson下的API使用例子:

步骤一:加入依赖

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>

步骤二:

parse方法的使用:例如把JSON文本parse为JSONObject或者JSONArray

更多参考:https://www.cnblogs.com/sunp823/p/5601399.html

1.根据json树treeId查找json并返回给前端:

controller:

/**
* @param treeId
* @return
*/
@ApiOperation(value="查询树信息", notes="查询树信息")
@RequestMapping(value = "/api/v1/orders/findTree" ,method = RequestMethod.POST)
public Map findTree(@ApiParam(required = true, value = "树id") @RequestParam Integer treeId
){
return ActionHelper.responseOk(categoryTreeService.getJsonTree(treeId));
}

service:

 //根据id获取json树
public JSONArray getJsonTree(Integer treeId){
JSONArray jsonTree = JSONArray.parseArray(categoryTreeRepository.selectJsonTree(treeId));
return jsonTree;
}

2.查找指定treeId的json树下对应的key-value的节点信息

controller:

/**
* @param treeId 树id
* @param key key名称
* @param value value值
* @return
*/
@ApiOperation(value="查询节点信息", notes="查询节点信息")
@RequestMapping(value = "/api/v1/orders/findNode" ,method = RequestMethod.POST)
public Map findNode(@ApiParam(required = true, value = "树id") @RequestParam Integer treeId,
@ApiParam(required = true, value = "节点key") @RequestParam String key,
@ApiParam(required = true, value = "节点value") @RequestParam String value
){
return ActionHelper.responseOk(categoryTreeService.getNode(treeId,key,value));
}

service:

//根据节点key-value键值对,获取树下该节点信息
public JSONObject getNode(Integer treeId,String key,String value){
JSONArray jsonTree = JSONArray.parseArray(categoryTreeRepository.selectJsonTree(treeId));
JSONObject node = getNode(jsonTree, key, value,new JSONObject());
return node;
} /**
* 根据单一条件获取节点位置
* @param body 查询目标的主体内容
* @param key 筛选匹配条件条件对应--key
* @param value 筛选匹配条件对应--value
* @param result 缓存查询结果
* @return
*/
public static JSONObject getNode(JSONArray body,String key,Object value,JSONObject result) {
for (int i = 0; i < body.size(); i++) {
JSONObject jsonObject =body.getJSONObject(i);
if (jsonObject.get(key).toString().equals(value.toString())) {
for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
result.put(entry.getKey(), entry.getValue());
}
}else if(jsonObject.getJSONArray("children")!=null) {
getNode(jsonObject.getJSONArray("children"), key, value,result);
}
}
return result;
}

3.删除指定treeId下的指定key-value的节点

controller:

  @ApiOperation(value="删除节点信息", notes="删除节点信息")
@RequestMapping(value = "/api/v1/orders/deldNode" ,method = RequestMethod.POST)
public Map delNode(@ApiParam(required = true, value = "树id") @RequestParam Integer treeId,
@ApiParam(required = true, value = "节点key") @RequestParam String key,
@ApiParam(required = true, value = "节点value") @RequestParam String value
){
return ActionHelper.responseOk(categoryTreeService.delNode(treeId,key,value));
}

service:

 //删除json树下指定的节点及其子节点
public JSONObject delNode(Integer treeId,String key,String value){
JSONArray jsonTree = JSONArray.parseArray(categoryTreeRepository.selectJsonTree(treeId));
JSONObject node = getNode(jsonTree, key, value,new JSONObject());
delNode(jsonTree, key, value);
String a=jsonTree.toString();
categoryTreeRepository.updateTree(a,treeId);
return node;
} /**
* 根据单一条件删除节点
* @param body 需要删除的目标主体
* @param key 筛选匹配条件对应的key
* @param value 筛选匹配条件对应的value
*/
public void delNode(JSONArray body,String key,Object value) {
for (int i = 0; i < body.size(); i++) {
JSONObject jsonObject =body.getJSONObject(i);
if (jsonObject.get(key).toString().equals(value.toString())) {
Object obj= body.remove(i);
break;
}else if(jsonObject.getJSONArray("children")!=null) {
delNode(jsonObject.getJSONArray("children"), key, value);
}
} }

mapper:

public interface CategoryTreeRepository extends JpaRepository<CategoryTree,String>, JpaSpecificationExecutor<CategoryTree> {
//根据id获取json树字符串
@Query(value="SELECT jsonTree from catagory_tree where id=?1",nativeQuery=true)
String selectJsonTree(Integer id); @Modifying
@Transactional
@Query(value="UPDATE catagory_tree SET jsonTree = ?1 WHERE id = ?2",nativeQuery = true)
void updateTree(String jsonTreeStr,Integer id); }

4.在指定的key-value键值对节点下面添加节点,

  目的:children的value为JsonArray格式,在此属性下添加JsonObject节点

  依旧走步骤2判断节点是否存在,若存在则:

  1.判断此节点下是否存在key为children的属性:

  2.如果此节点存在key为children的属性,则在children下指定下标添加节点

  3.如果不存在key为children的属性,则添加children,新节点存进children

controller:

  @ApiOperation(value="新建节点", notes="根据输入参数创建节点")
@RequestMapping(value = "/tree_data/node/{treeId}", method = RequestMethod.POST)
public Map addOne(@ApiParam(required = true, value = "分类树ID")@PathVariable Integer treeId,
@ApiParam(required = true, value = "节点key") @RequestParam String key,
@ApiParam(required = true, value = "节点value") @RequestParam String value,
@ApiParam(required = true, value = "插入下标") @RequestParam Integer index,
@ApiParam(required = true, value = "节点信息") @RequestBody Map map){
return ActionHelper.responseOk(categoryTreeService.addNode(treeId,key,value,index,map));
}

service:

 //在json树下添加节点:
public JSONArray addNode(Integer treeId,String key,Object value,Integer sequ,Map newNodeMap){
JSONArray jsonTree = JSONArray.parseArray(categoryTreeRepository.selectJsonTree(treeId));
Integer nodeId = (Integer)newNodeMap.get("id");
JSONObject node = getNode(jsonTree, "id", nodeId,new JSONObject());
System.out.println(node);
if(!node.isEmpty()){
throw new BadRequestException("此id的节点已存在");
}
//把map转化为JSONObject
JSONObject newNode = new JSONObject(newNodeMap);
addNode(jsonTree,key,value,sequ, newNode);
return jsonTree;
} /**
* 增加节点
* @param jsonArray 需要更新的目标主体
* @param node 增加节点信息
* @param sequ 数组的位置
* @param key 目标主体中的字段名key
* @param value 节点信息与key对应的value
*/
public void addNode(JSONArray jsonArray, String key, Object value, Integer sequ,JSONObject node) {
for (Object obj : jsonArray) {
JSONObject jsonObject = (JSONObject) obj;
JSONArray children = jsonObject.getJSONArray("children");
if (children != null) {
if (value.toString().equals(jsonObject.get(key).toString())) {
if(sequ > children.size()){
//如果下标大于此节点children的长度,则追加
children.add(children.size(), node);
}else{
//在指定位置增加
children.add(sequ-1, node);
}
return;
}
addNode(children,key,value,sequ,node);
} else {
//直接判断是否要在此节点下增加个名为children键值对
if (value.toString().equals(jsonObject.get(key).toString())) {
JSONArray array = new JSONArray();
array.add(node);
jsonObject.put("children", array);
return;
}
}
}
}

5.根据节点id更改节点属性:

  涉及API:jsonObject.put(key,value)

  依旧先走步骤2查询节点是否存在,若存在则更改属性:

  如果更改的属性存在,则覆盖

  如果更改的属性不存在,则追加

controller:

@ApiOperation(value="更新节点信息", notes="更新节点信息")
@RequestMapping(value = "/tree_data/node/{treeId}/{id}", method = RequestMethod.PATCH)
public Map updateOne(@ApiParam(required = true, value = "分类树ID")@PathVariable Integer treeId,
@ApiParam(required = true, value = "节点ID")@PathVariable Integer id,
@ApiParam(required = true, value = "节点信息") @RequestBody Map map){
return ActionHelper.responseOk(categoryTreeService.updateNode(treeId,id,map));
}

service:

/**
* 修改单个节点
* @param treeId
* @param nodeId
* @param map
* @return
*/
@Transactional
public JSON updateNode(Integer treeId, Integer nodeId, Map map) {
JSONArray jsonTree = JSONArray.parseArray(categoryTreeRepository.selectJsonTree(treeId));
//查询节点是否存在
if(!getNode(jsonTree, "id", nodeId,new JSONObject()).isEmpty()){
update(jsonTree, "id", nodeId, map);
//更新数据库
String a=jsonTree.toString();
categoryTreeRepository.updateTree(a,treeId);
}else{
throw new BadRequestException("此id的节点不存在");
}
return jsonTree; } /**
* 根据条件更新节点
* @param jsonArray 需要更新的目标主体
* @param key 目标主体中的字段名key
* @param value 更新节点信息与key对应的value
* @param map 更新节点信息
*/
public void update(JSONArray jsonArray, String key, Object value, Map<String,Object> map) {
for (int i = 0; i < jsonArray.size() ; i++) {
JSONObject json=jsonArray.getJSONObject(i);
if(value.toString().equals(json.get(key).toString())){
for (Map.Entry<String,Object> entry : map.entrySet()) {
json.put(entry.getKey(),entry.getValue());
}
break;
}else if(json.getJSONArray("children")!=null) {
update(json.getJSONArray("children"), key, value,map);
}
}
}

FastJson:Json树的CRUD操作方法实现的更多相关文章

  1. JSON树节点的增删查改

    最近了解到使用json字符串存到数据库的一种存储方式,取出来的json字符串可以进行相应的节点操作 故借此机会练习下递归,完成对json节点操作对应的工具类. 介绍一下我使用的依赖 复制代码 < ...

  2. jquery: json树组数据输出到表格Dom树的处理方法

    项目背景 项目中需要把表格重排显示 处理方法 思路主要是用历遍Json数组把json数据一个个append到5个表格里,还要给每个单元格绑定个单击弹出自定义对话框,表格分了单双行,第一行最后还要改ro ...

  3. com.alibaba.fastjson.JSON对类对象的序列化与反序列化

    1. 目标 把类的对象存储到字符串可存储 2. 类定义 public interface JsonInterface { } mport com.alibaba.fastjson.JSON; impo ...

  4. json树递归js查询json父子节点

    上代码,直接另存为html打开,看console控制台就可以看到效果了 <!DOCTYPE html> <html lang="en"> <head& ...

  5. 递归遍历JSON树

    递归遍历JSON树 前几天有个人问我,json串的层级无限深,但在json串中的key是已知的,在json串中的value,有些事Object,有些是Array,如何把这些层级无限深的key所对应的v ...

  6. (转载)JavaScript递归查询 json 树 父子节点

    在Json中知道某个属性名,想要确定该属性在Json树具体的节点,然后进行操作还是很麻烦的 可以用以下方法找到该属性所在的节点,和父节点 <!DOCTYPE html> <html ...

  7. Vue之使用JsonView来展示Json树

    前两天干活儿有个需求,在前端需要展示可折叠的Json树,供开发人员查看,这里采用JsonView组件来实现,它是一款用于展示Json的Vue组件,支持大体积的Json文件快速解析渲染,下面记录一下实现 ...

  8. com.alibaba.fastjson.JSON.parseObject

    Journal 日志实体 Journal journal = com.alibaba.fastjson.JSON.parseObject(jsonStr, new com.alibaba.fastjs ...

  9. fastjson JSON.toJavaObject() 实体类首字母大写属性无法解析问题

    fastjson JSON.toJavaObject() 实体类首字母大写属性无法解析问题

随机推荐

  1. unity发布的WebGL部署到IIS

    一.创建WebGL代码 在win7下,Unity3D中发布WebGL,然后部署到IIS,只要代码是对,关键是添加mime类型 二.为网站添加mime类型 .json text/json .unity3 ...

  2. vue 报错总结

    关闭vue-cli 默认eslint规则: 找到 build -> webpack.base.config.js ,删除箭头指向代码 1.Newline required at end of f ...

  3. http协议——无连接、无状态

    无连接 无连接的含义是限制每次连接只处理一个请求.服务器处理完客户的请求,并收到客户的应答后,即断开连接.采用这种方式可以节省传输时间. 早期这么做的原因是 HTTP 协议产生于互联网,因此服务器需要 ...

  4. 【原创】大数据基础之Oozie vs Azkaban

    概括 Azkaban是一个非常轻量的开源调度框架,适合二次开发,但是无法直接用于生产环境,存在致命缺陷(比如AzkabanWebServer是单点,1年多时间没有修复),在一些情景下的行为简单粗暴(比 ...

  5. js小方法,获取知道公历生日 (‘1992-01-19’),获取阴历生日日期,属相,非简单根据年份判断-----------声明:整理自网络!!

    let lunar = { tg: '甲乙丙丁戊己庚辛壬癸', dz: '子丑寅卯辰巳午未申酉戌亥', number: '一二三四五六七八九十', year: '鼠牛虎兔龙蛇马羊猴鸡狗猪', mont ...

  6. ajax与后台交互案例

    BBS项目 //BBS项目,注册页面ajax请求 // 1.实现照片预览 $("#up_myhead").change(function () { // 获取input选择的文件 ...

  7. 利用Graphviz绘制逻辑关系依赖图

    说明:在很多情况下,需要将复杂且有些规律的代码整理成逻辑片段,这个时候就需要画图,很多时候图比代码更加直观 Graphviz是一个比较好的绘图工具,可以通过简单的代码绘制出复杂的逻辑图,且其代码就像平 ...

  8. C++线程中的几种锁

    线程之间的锁有:互斥锁.条件锁.自旋锁.读写锁.递归锁.一般而言,锁的功能越强大,性能就会越低. 1.互斥锁 互斥锁用于控制多个线程对他们之间共享资源互斥访问的一个信号量.也就是说是为了避免多个线程在 ...

  9. android setCompoundDrawables和setCompoundDrawablesWithIntrinsicBounds区别

    手工设置文本与图片相对位置时,常用到如下方法: setCompoundDrawables(left, top, right, bottom) setCompoundDrawablesWithIntri ...

  10. 关于getchar-scanf函数的相关坑!

    首先,我们编写如下所示的代码: #include <stdio.h> void test(int n) { ; ; ; a = b; b = c; c = n; printf(" ...