前言
自动化测试下为了使一个json 串适用于多种用例场景,经常涉及到对json深层数据的读取和更改,小结一下。
github上最新tag是1.2.80了,还是用最新releases版本
https://github.com/alibaba/fastjson/releases
一、配置及示例
pom.xml配置
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.79</version>
</dependency>
示例json,为了方便看,我把viewConfig展开了,但是实际上前端传入的时候,它和processConfig 是一样的,就是堆在一起的一个长字符串(为了便于数据库存储写成了长字符串)
{
"name": "namevalue",
"description": "desc",
"ruleType": "modify",
"viewConfig":
"{
\"graph\":
{
\"nodes\":
[
{
\"label\": \"自然人1\",
\"data\":
{
\"id\": 123456,
\"uuid\": \"20220331193148836884f21e062db4e0\",
\"name\": \"person1\",
\"cname\": \"自然人1\",
\"type\": \"vertex\"
},
\"id\": \"83f03a5c\",
\"index\": 0
},
{
\"label\": \"自然人2\",
\"data\":
{
\"id\": 123457,
\"uuid\": \"20220331193148836884f21e062db4e0\",
\"name\": \"person2\",
\"cname\": \"自然人\",
\"type\": \"vertex\"
},
\"id\": \"da888c44\",
\"index\": 1
}
],
\"edges\":
[]
},
\"type\": \"modify\"
}",
"processConfig": "{\"graph\":
{\"vertices\":[{\"id\":\"83f03a5c\",\"label\":\"person\",\"filter\":\"\"},{\"id\":\"da888c44\",\"label\":\"person\",\"filter\":\"\"}],\"edges\":[]},\"inferResult\":{\"label\":\"invest\",\"edges\":[{\"outVertex\":\"83f03a5c\",\"inVertex\":\"83f03a5c\",\"props\":{}}],\"filter\":{\"type\":\"custom\",\"filter\":{}}},\"type\":\"modify\"}",
"workspaceUuid": "202203311931486655f959ad67b724a3"
}
二、 json深层路径读取
/*设如上json串为 reqJson,若要读取 name person1 */
JSONPath.read(reqJson,"$.viewConfig.graph.nodes[0].data.name").toString();
/*设如上json串为 reqJson,若要读取 name person2 */
JSONPath.read(reqJson,"$.viewConfig.graph.nodes[1].data.name").toString();
三、json 深层路径值更新
设如上json串为 reqJson 若要设置 id 123456为 654321
目前fastjson可以正常支持的操作:
JSONObject reqJb = JSONObject.parseObject(reqJson);
JSONObject viewConfigJb = JSONObject.parseObject(reqJb.get("viewConfig").toString());
JSONPath.set(viewConfigJb, "$.graph.nodes[0].data.id",new Integer(654321));
reqJb.put("viewConfig",viewConfigJb.toJSONString());
理想情况下,应该是这样子的,而对于示例json,如下操作无法实现参数值更新
JSONObject reqJb = JSONObject.parseObject(reqJson);
JSONPath.set(reqJb, "$.viewConfig.graph.nodes[0].data.id",new Integer(654321));
调试过fastjson的实现方式后发现,JSONPath.set函数实现深层路径更新的前提是,第一个参数jsonObject需要已经被逐层解析为一个Json对象(包括JSONArray),而JSONObject.parseObject(reqJson)处理后的获得的reqJb的属性viewConfig 的值是一个长字符串,不是一个被逐层解析过的迭代对象;JSONObject.parseObject(reqJb.get(“viewConfig”).toString())获取到的viewConfigJb 是一个完整的经过逐级解析过的JSONObject对象,因此可以直接实现深度更新。
by the way,JSONPath.set(reqJb, “$.viewConfig.graph.nodes[0].data.id”,new Integer(654321)) 深度更新的时候,其实代码执行是可以正常获取到最深度一层的JSONObject对象的,只不过因为该对象不是reqJb深层指向的对象,所以无法更新成功,可以理解为fastjson的一个待优化缺陷了,有时间再研究下。
如果json为如下这种格式,viewConfig的值直接为一个json,那么就可以直接使用理想的方式去做深度更新,因为JSONObject.parseObject会将json串直接解析成为一个完整的逐层JSONObject.parseObject 的对象格式。
{
"name": "namevalue",
"description": "desc",
"ruleType": "modify",
"viewConfig":
{
"graph":
{
"nodes":
[
{
"label": "自然人1",
"data":
{
"id": 263121,
"uuid": "20220331193148836884f21e062db4e0",
"name": "person",
"cname": "自然人",
"type": "vertex"
},
"id": "83f03a5c",
"index": 0
},
{
"label": "自然人2",
"data":
{
"id": 263121,
"uuid": "20220331193148836884f21e062db4e0",
"name": "person",
"cname": "自然人",
"type": "vertex"
},
"id": "da888c44",
"index": 1
}
],
"edges":
[]
},
"type": "modify"
},
"workspaceUuid": "202203311931486655f959ad67b724a3"
}