少年最好的地方就是:嘴里说着要放弃,心里却都憋着一口气。
前言
关于JSON和本文中所用的Fastjson介绍,可以查看我的这两篇博客:
JSON简介:什么是JSON -> https://blog.csdn.net/Qizhi_Hu/article/details/105305616
JSON解析之Fastjson:https://blog.csdn.net/Qizhi_Hu/article/details/105315629
最近有朋友问了我个关于JSON转换的问题,问题描述如下:
需要将从其他系统接收到的JSON数据,解析成规定的数据,然后渲染给前端
乍一听,这个问题很简单,但是这个JSON数据又臭又长,规定的数据又奇奇怪怪,可能是因为之前没有处理过,所以让我朋友很是犯难☹
当然了,其实这个问题其实就是很简单
首先我们来看一下接收的JSON数据:
[{
"object": [{
"content": 103,
"name": "编码",
"code": "code"
}, {
"content": "经理层(部门)",
"name": "名称",
"code": "name"
}, {
"content": "0001A110000000002D15",
"name": "上级部门",
"code": "pk_fatherorg"
}, {
"content": 10,
"name": "上级业务单元编码",
"code": "fatherorg_code"
}, {
"content": "中南控股集团有限公司",
"name": "上级业务单元名称",
"code": "fatherorg_name"
}, {
"content": "中南集团",
"name": "所属集团名称",
"code": "group_name"
}, {
"content": "1001B210000000EQ6D5U",
"name": "组织主键",
"code": "pk_org"
}, {
"content": 0,
"name": "删除标志",
"code": "dr"
}, {
"content": "2020-01-02 11:26:25",
"name": "时间戳",
"code": "ts"
}, {
"content": "Y",
"name": "是否生效状态",
"code": "iseffect"
}, {
"content": "控股",
"name": "所属产业",
"code": "corp"
}]
}, {
"object": [{
"content": 102,
"name": "编码",
"code": "code"
}, {
"content": "董事会(部门)",
"name": "名称",
"code": "name"
}, {
"content": "0001A110000000002D15",
"name": "上级部门",
"code": "pk_fatherorg"
}, {
"content": 10,
"name": "上级业务单元编码",
"code": "fatherorg_code"
}, {
"content": "中南控股集团有限公司",
"name": "上级业务单元名称",
"code": "fatherorg_name"
}, {
"content": "中南集团",
"name": "所属集团名称",
"code": "group_name"
}, {
"content": "1001B210000000EQ6D61",
"name": "组织主键",
"code": "pk_org"
}, {
"content": 0,
"name": "删除标志",
"code": "dr"
}, {
"content": "2018-11-21 09:06:00",
"name": "时间戳",
"code": "ts"
}, {
"content": "Y",
"name": "是否生效状态",
"code": "iseffect"
}, {
"content": "控股",
"name": "所属产业",
"code": "corp"
}]
}]
emmmm,不知道有多少人能看到这里,可能很多人看到这么长串的JSON数据跟我以前一样心里直接就发慌了。但是别怕,我们先运用抽象思维,简化出一个JSON数据模型,看看它到底是个什么妖魔鬼怪:
[{
"object": [{
"content": "103",
"name": "编码",
"code": "code"
},{
"content": "控股",
"name": "所属产业",
"code": "corp"
}]
}, {
"object": [{
"content": 102,
"name": "编码",
"code": "code"
},{
"content": "控股",
"name": "所属产业",
"code": "corp"
}]
}]
原来它就是一个以JSON数组对象为元素构成的一个JSON数组,心中大定!
我们再来看一下需要解析成的数据格式:
[{
"code":"103",
"corp":"控股",
"dr":"0",
"fatherorg_code":"10",
"fatherorg_name":"中南控股集团有限公司",
"group_name":"中南集团",
"iseffect":"Y",
"name":"经理层(部门)",
"pk_fatherorg":"0001A110000000002D15",
"pk_org":"1001B210000000EQ6D5U",
"ts":"2020-01-02 11:26:25"
},{
"code":"102",
"corp":"控股",
"dr":"0",
"fatherorg_code":"10",
"fatherorg_name":"中南控股集团有限公司",
"group_name":"中南集团",
"iseffect":"Y",
"name":"董事会(部门)",
"pk_fatherorg":"0001A110000000002D15",
"pk_org":"1001B210000000EQ6D61",
"ts":"2018-11-21 09:06:00"
}]
纳尼,这是个什么?仔细观察后发现之前接收到的JSON数组中的每一个小数组中每一个JSON对象的code所对应的值作为属性名取出来,content对应的值作为属性值,然后再构成一个新的JSON对象,再由这一个个JSON对象构成一个JSON数组就ok了。
开始编码
编码思路
- 首先遍历大的JSON数组,得到一个个小的JSON数组对象
- 将小的JSON数组对象转换成为JSON数组对象字符串
类似于:
"object": [{
"content": 102,
"name": "编码",
"code": "code"
},{
"content": "控股",
"name": "所属产业",
"code": "corp"
}]
- 将JSON数组对象字符串切割成标准的JSON数组字符串
如:
[{
"content": 102,
"name": "编码",
"code": "code"
},{
"content": "控股",
"name": "所属产业",
"code": "corp"
}]
然后便可以进行正常操作,按要求获取数据。
另外,为了防止出现转义字符("\")等特殊字符使得Fastjson无法解析,所以我们最好将属性值先用"Unicode"格式编码再用"Unicode"格式进行解码。
代码示例
先建立一个输出模板类,方便处理JSON数据
/**
* @author guqueyue
* @Date 2020/4/4
* VO:输出模板
**/
@Data // lombok插件的注解,若是没有用lombok插件,请自行生成getter、setter方法
public class VO {
private String code;
private String name;
private String pk_fatherorg;
private String fatherorg_code;
private String fatherorg_name;
private String group_name;
private String pk_org;
private String dr;
private String ts;
private String iseffect;
private String corp;
}
核心代码,解释都在注释里
/**
* @author guqueyue
* @Date 2020/4/5
* JSON数组中每个元素为JSON数组的示例解析
**/
public class JSONTest {
public static void main(String[] args) throws Exception {
// 声明接收到的JSON字符串
String jsonString = "[{\n" +
" \"object\": [{\n" +
" \"content\": 103,\n" +
" \"name\": \"编码\",\n" +
" \"code\": \"code\"\n" +
" }, {\n" +
" \"content\": \"经理层(部门)\",\n" +
" \"name\": \"名称\",\n" +
" \"code\": \"name\"\n" +
" }, {\n" +
" \"content\": \"0001A110000000002D15\",\n" +
" \"name\": \"上级部门\",\n" +
" \"code\": \"pk_fatherorg\"\n" +
" }, {\n" +
" \"content\": 10,\n" +
" \"name\": \"上级业务单元编码\",\n" +
" \"code\": \"fatherorg_code\"\n" +
" }, {\n" +
" \"content\": \"中南控股集团有限公司\",\n" +
" \"name\": \"上级业务单元名称\",\n" +
" \"code\": \"fatherorg_name\"\n" +
" }, {\n" +
" \"content\": \"中南集团\",\n" +
" \"name\": \"所属集团名称\",\n" +
" \"code\": \"group_name\"\n" +
" }, {\n" +
" \"content\": \"1001B210000000EQ6D5U\",\n" +
" \"name\": \"组织主键\",\n" +
" \"code\": \"pk_org\"\n" +
" }, {\n" +
" \"content\": 0,\n" +
" \"name\": \"删除标志\",\n" +
" \"code\": \"dr\"\n" +
" }, {\n" +
" \"content\": \"2020-01-02 11:26:25\",\n" +
" \"name\": \"时间戳\",\n" +
" \"code\": \"ts\"\n" +
" }, {\n" +
" \"content\": \"Y\",\n" +
" \"name\": \"是否生效状态\",\n" +
" \"code\": \"iseffect\"\n" +
" }, {\n" +
" \"content\": \"控股\",\n" +
" \"name\": \"所属产业\",\n" +
" \"code\": \"corp\"\n" +
" }]\n" +
"}, {\n" +
" \"object\": [{\n" +
" \"content\": 102,\n" +
" \"name\": \"编码\",\n" +
" \"code\": \"code\"\n" +
" }, {\n" +
" \"content\": \"董事会(部门)\",\n" +
" \"name\": \"名称\",\n" +
" \"code\": \"name\"\n" +
" }, {\n" +
" \"content\": \"0001A110000000002D15\",\n" +
" \"name\": \"上级部门\",\n" +
" \"code\": \"pk_fatherorg\"\n" +
" }, {\n" +
" \"content\": 10,\n" +
" \"name\": \"上级业务单元编码\",\n" +
" \"code\": \"fatherorg_code\"\n" +
" }, {\n" +
" \"content\": \"中南控股集团有限公司\",\n" +
" \"name\": \"上级业务单元名称\",\n" +
" \"code\": \"fatherorg_name\"\n" +
" }, {\n" +
" \"content\": \"中南集团\",\n" +
" \"name\": \"所属集团名称\",\n" +
" \"code\": \"group_name\"\n" +
" }, {\n" +
" \"content\": \"1001B210000000EQ6D61\",\n" +
" \"name\": \"组织主键\",\n" +
" \"code\": \"pk_org\"\n" +
" }, {\n" +
" \"content\": 0,\n" +
" \"name\": \"删除标志\",\n" +
" \"code\": \"dr\"\n" +
" }, {\n" +
" \"content\": \"2018-11-21 09:06:00\",\n" +
" \"name\": \"时间戳\",\n" +
" \"code\": \"ts\"\n" +
" }, {\n" +
" \"content\": \"Y\",\n" +
" \"name\": \"是否生效状态\",\n" +
" \"code\": \"iseffect\"\n" +
" }, {\n" +
" \"content\": \"控股\",\n" +
" \"name\": \"所属产业\",\n" +
" \"code\": \"corp\"\n" +
" }]\n" +
"}]";
// 声明对象集合,用来存储解析完成的数据
List<VO> voList = new ArrayList<VO>();
// JSON字符串转换成JSON大数组
JSONArray jsonBigArray = JSON.parseArray(jsonString);
// 遍历JSON大数组,得到每个JSON对象, 再把每个JSON对象处理成JSON数组
for (int i = 0; i < jsonBigArray.size(); i++) {
// 得到JSON对象
JSONObject jsonObject = jsonBigArray.getJSONObject(i);
// 得到JSON数组
JSONArray jsonSmallArray = toJSONArray(jsonObject);
// 通过JSON小数组,得到符合要求的JSON字符串
String jsonString1 = getJSONString(jsonSmallArray);
// 将JSON字符串解析成VO对象存入集合
voList.add(JSON.parseObject(jsonString1, VO.class));
}
// 对集合中对象的属性值进行解码
decodeList(voList);
System.out.println(voList);
}
/**
* 对集合中对象的属性值进行解码
* @param voList
* @return
*/
private static void decodeList(List<VO> voList) throws Exception {
for (VO vo : voList) {
// 得到反射对象
Class Clazz = vo.getClass();
// 通过反射对象获得这个类的所有属性对象
Field[] declaredFields = Clazz.getDeclaredFields();
// 遍历所有属性对象
for (Field field : declaredFields) {
// 设置属性对象访问权限
field.setAccessible(true);
// 获得当前遍历的属性对象的属性名
String name = field.getName();
// 获得属性值
String fieldValue = (String) field.get(vo);
// 解码
String unicode = "";
if(fieldValue != null) {
unicode = URLDecoder.decode(fieldValue, "Unicode");
}
// 重新赋值
field.set(vo, unicode);
}
}
}
/**
* 遍历JSON小数组,根据要求拼接成新的json字符串
* @param jsonSmallArray
* @return
*/
private static String getJSONString(JSONArray jsonSmallArray) throws UnsupportedEncodingException {
String jsonString = "{";
for (int j = 0; j < jsonSmallArray.size(); j++) {
// 取出数组中键名为code对应的值
String code = jsonSmallArray.getJSONObject(j).getString("code");
// 取出数组中键名为content对应的值
String content = jsonSmallArray.getJSONObject(j).getString("content");
//为了防止属性值遇到转义字符("\")等特殊字符,先用"Unicode"进行编码
if (content != null) {
content= URLEncoder.encode(content, "Unicode");
}
// 拼接
jsonString += "\"" + code + "\":\"" + content+ "\",";
}
// 去掉最后的逗号, 再加上 }
jsonString = jsonString.substring(0, jsonString.length()-1) + "}";
return jsonString;
}
/**
* 将JSON对象数组处理成JSON数组
* 如: {"object":[{name:"小明", age:18}, {name:"小晏", age:11}]}
* 转换成 -> [{name:"小明", age:18}, {name:"小晏", age:11}]
* @param jsonObject
* @return
*/
private static JSONArray toJSONArray(JSONObject jsonObject) {
// 把JSON对象转换成JSON字符串
String str = JSON.toJSONString(jsonObject);
// 把JSON字符串切割成符合要求的JSON数组字符串
String substring = str.substring(10, str.length() - 1);
// 把JSON字符串转换成JSON数组
JSONArray jsonArray = JSON.parseArray(substring);
return jsonArray;
}
}
Output:
之后用@ResposeBoby或者@RestController注解将Java集合渲染回前端就行,框架自会帮你转成JSON格式的数据。不过还是感觉代码有些冗余,如有更好的方法或者我的方法有能改进的地方,还望看到的朋友不吝赐教 !
查看升级版本,请点击:JSON解析实战升级篇
----------------------------------2020-04-07 20:13:66-------------------------------------------