背景
在某些系统当中,我们经常在前端看到一些操作的滚动屏,例如:“谁谁谁登录了系统”,“谁谁谁提交了***号订单”,所以突发奇想,能否在部分接口上
通过自定义注解生成滚动内容,然后推送到前端或者保存至数据库呢?
例如:
@RollRecord("${customParam.nickName}操作了客户${requestParam.customerName}的订单,并生成订单号${returnBody.orderNumber}")
@RollRecord("${customParam.nickName}批量接取了${returnbody[*].orderNumber}")订单
这样能使得代码具有更少的侵入性。
至于,注解里面的表达式的取值,我们可以提供一个ThreadLocal<String,Object> 类型变量 rollRecordContextParam来保存,一个默认把请求参数requestParam,以及返回参数returnBody放入,以及部分特殊需要扩展的需求可以通过customParam(Map<String,Object>)在业务中放入.
由此可知rollRecordContextParam的基本结构应该是:{requestParam:{},returnBody:{},customParam:{}};
那么问题来了,如何通过 “customParam.nickName”,“returnbody[*].orderNumber”这种表达式去取rollRecordContextParam当中的值呢?
问题
在js当中,面对一个json对象,我们可以直接通过user.id,user[0].name来获取json对象的值。
那么,我们能够通过Java来实现这种效果,或者扩展呢?
目标效果:
给定如下数据:
{ "code":200, "data":{ "current":1, "pages":1, "records":[ { "bindAccount":"A202203030000002", "bindCustomer":"C2022030300001", "bindStatus":true, "contactEmail":null, "contactMobile":"", "contactName":"", "ctdTime":"2022-03-03 10:17:39", "customerInfo":{ "cooperate":true, "ctdTime":"2022-03-03 10:14:53", "customerCode":"CSKHFJX", "customerName":"测试客户发件箱新增", "customerSimpleName":"测试客户发件箱新增", "customerUnId":"C2022030300001", "dealRemark":"", "delegate":0, "delegateUrl":null, "globalId":"C2021121700002", "id":32, "remark":"", "types":[ "BG" ], "updTime":"2022-03-03 10:14:53" }, "employeeInfo":{ "accountName":"CKF001", "accountUnId":"A202203030000002", "ctdTime":"2022-03-03 10:16:11", "departmentName":"", "email":null, "employeeNo":"", "globalId":"C2021121700002", "headUrl":null, "id":67, "idNumber":null, "lastLoginTime":"2022-03-04 10:36:02", "locked":false, "mobile":"14566666666", "password":"$2a$10$wVm3Uz4pe9WBvkZXzB8LjOyzBKXY92PKpS7vo0YNyv9j0Pa3ZBu86", "passwordExpireTime":"2022-06-01 10:16:10", "qq":null, "realName":"测客发001", "superAdmin":false, "updTime":"2022-03-03 10:16:11", "workStatus":0, "wx":null }, "globalId":"C2021121700002", "id":34, "remark":"ceshikehufajiangxiangxinzeng", "sendEmail":"68944442@qq.com", "updTime":"2022-03-03 10:17:39" }, { "bindAccount":"A202112250000001", "bindCustomer":"C2022030200001", "bindStatus":true, "contactEmail":null, "contactMobile":"", "contactName":"", "ctdTime":"2022-03-03 10:11:56", "customerInfo":{ "cooperate":true, "ctdTime":"2022-03-02 18:33:52", "customerCode":"HAIHAI", "customerName":"杭州嗨嗨厂", "customerSimpleName":"嗨嗨", "customerUnId":"C2022030200001", "dealRemark":"", "delegate":0, "delegateUrl":null, "globalId":"C2021121700002", "id":31, "remark":"", "types":[], "updTime":"2022-03-02 18:33:52" }, "employeeInfo":null, "globalId":"C2021121700002", "id":33, "remark":"", "sendEmail":"9999999999@qq.com", "updTime":"2022-03-03 10:11:56" }, { "bindAccount":"A202112250000001", "bindCustomer":"C2022030200001", "bindStatus":true, "contactEmail":null, "contactMobile":"", "contactName":"", "ctdTime":"2022-03-02 18:34:31", "customerInfo":{ "cooperate":true, "ctdTime":"2022-03-02 18:33:52", "customerCode":"HAIHAI", "customerName":"杭州嗨嗨厂", "customerSimpleName":"嗨嗨", "customerUnId":"C2022030200001", "dealRemark":"", "delegate":0, "delegateUrl":null, "globalId":"C2021121700002", "id":31, "remark":"", "types":[], "updTime":"2022-03-02 18:33:52" }, "employeeInfo":null, "globalId":"C2021121700002", "id":31, "remark":"", "sendEmail":"1019486403@qq.com", "updTime":"2022-03-02 18:34:31" } ], "size":10, "total":3 }, "developerMessage":null, "msg":"success" }
通过以下代码取下列表达式的值
- "data.records[0].customerInfo.customerName"
- "data.records[*].customerInfo.customerName"
- "code"
public static void main(String[] args) throws IOException {
String express1 = "data.records[0].customerInfo.customerName";
String express2 = "data.records[*].customerInfo.customerName";
String express3 = "code";
String jsonContent1 = "{ \"code\":200, \"data\":{ \"current\":1, \"pages\":1, \"records\":[ { \"bindAccount\":\"A202203030000002\", \"bindCustomer\":\"C2022030300001\", \"bindStatus\":true, \"contactEmail\":null, \"contactMobile\":\"\", \"contactName\":\"\", \"ctdTime\":\"2022-03-03 10:17:39\", \"customerInfo\":{ \"cooperate\":true, \"ctdTime\":\"2022-03-03 10:14:53\", \"customerCode\":\"CSKHFJX\", \"customerName\":\"测试客户发件箱新增\", \"customerSimpleName\":\"测试客户发件箱新增\", \"customerUnId\":\"C2022030300001\", \"dealRemark\":\"\", \"delegate\":0, \"delegateUrl\":null, \"globalId\":\"C2021121700002\", \"id\":32, \"remark\":\"\", \"types\":[ \"BG\" ], \"updTime\":\"2022-03-03 10:14:53\" }, \"employeeInfo\":{ \"accountName\":\"CKF001\", \"accountUnId\":\"A202203030000002\", \"ctdTime\":\"2022-03-03 10:16:11\", \"departmentName\":\"\", \"email\":null, \"employeeNo\":\"\", \"globalId\":\"C2021121700002\", \"headUrl\":null, \"id\":67, \"idNumber\":null, \"lastLoginTime\":\"2022-03-04 10:36:02\", \"locked\":false, \"mobile\":\"14566666666\", \"password\":\"$2a$10$wVm3Uz4pe9WBvkZXzB8LjOyzBKXY92PKpS7vo0YNyv9j0Pa3ZBu86\", \"passwordExpireTime\":\"2022-06-01 10:16:10\", \"qq\":null, \"realName\":\"测客发001\", \"superAdmin\":false, \"updTime\":\"2022-03-03 10:16:11\", \"workStatus\":0, \"wx\":null }, \"globalId\":\"C2021121700002\", \"id\":34, \"remark\":\"ceshikehufajiangxiangxinzeng\", \"sendEmail\":\"68944442@qq.com\", \"updTime\":\"2022-03-03 10:17:39\" }, { \"bindAccount\":\"A202112250000001\", \"bindCustomer\":\"C2022030200001\", \"bindStatus\":true, \"contactEmail\":null, \"contactMobile\":\"\", \"contactName\":\"\", \"ctdTime\":\"2022-03-03 10:11:56\", \"customerInfo\":{ \"cooperate\":true, \"ctdTime\":\"2022-03-02 18:33:52\", \"customerCode\":\"HAIHAI\", \"customerName\":\"杭州嗨嗨厂\", \"customerSimpleName\":\"嗨嗨\", \"customerUnId\":\"C2022030200001\", \"dealRemark\":\"\", \"delegate\":0, \"delegateUrl\":null, \"globalId\":\"C2021121700002\", \"id\":31, \"remark\":\"\", \"types\":[], \"updTime\":\"2022-03-02 18:33:52\" }, \"employeeInfo\":null, \"globalId\":\"C2021121700002\", \"id\":33, \"remark\":\"\", \"sendEmail\":\"9999999999@qq.com\", \"updTime\":\"2022-03-03 10:11:56\" }, { \"bindAccount\":\"A202112250000001\", \"bindCustomer\":\"C2022030200001\", \"bindStatus\":true, \"contactEmail\":null, \"contactMobile\":\"\", \"contactName\":\"\", \"ctdTime\":\"2022-03-02 18:34:31\", \"customerInfo\":{ \"cooperate\":true, \"ctdTime\":\"2022-03-02 18:33:52\", \"customerCode\":\"HAIHAI\", \"customerName\":\"杭州嗨嗨厂\", \"customerSimpleName\":\"嗨嗨\", \"customerUnId\":\"C2022030200001\", \"dealRemark\":\"\", \"delegate\":0, \"delegateUrl\":null, \"globalId\":\"C2021121700002\", \"id\":31, \"remark\":\"\", \"types\":[], \"updTime\":\"2022-03-02 18:33:52\" }, \"employeeInfo\":null, \"globalId\":\"C2021121700002\", \"id\":31, \"remark\":\"\", \"sendEmail\":\"1019486403@qq.com\", \"updTime\":\"2022-03-02 18:34:31\" } ], \"size\":10, \"total\":3 }, \"developerMessage\":null, \"msg\":\"success\" }";
System.out.println(getJsonContentByExpress(express1,jsonContent1));
System.out.println(getJsonContentByExpress(express2,jsonContent1));
System.out.println(getJsonContentByExpress(express3,jsonContent1));
}
输出下面的结果:
开始编码
依赖准备:
fastjson
google guva
common-lang3
工具代码:
public static String getJsonContentByExpress(String express,String jsonContent){
List<JsonFiledInfo> jsonFiledInfos = analyseExpress(express);
return getByJsonFieldInfos(jsonFiledInfos, jsonContent);
}
public static List<JsonFiledInfo> analyseExpress(String express) {
List<JsonFiledInfo> jsonFiledInfos = new ArrayList<>();
List<String> params = string2List(express, ".");
for (String param : params) {
List<String> ps = string2List(param, "[");
for (String p : ps) {
JsonFiledInfo jsonFiledInfo = new JsonFiledInfo();
if (p.contains("]")) {
List<String> ss = string2List(p, "]");
jsonFiledInfo.setField(ss.get(0));
jsonFiledInfo.setType(JsonFiledInfo.ARRAY_TYPE);
boolean f = ss.get(0).startsWith("'") && ss.get(0).endsWith("'");
boolean ff = ss.get(0).startsWith("\"") && ss.get(0).endsWith("\"");
if (f || ff) {
String str = ss.get(0);
jsonFiledInfo.setField(str.substring(1, str.length() - 1));
jsonFiledInfo.setType(JsonFiledInfo.OBJECT_TYPE);
}
jsonFiledInfos.add(jsonFiledInfo);
if (ss.size() > 1) {
JsonFiledInfo jfi = new JsonFiledInfo();
jfi.setField(ss.get(1));
jfi.setType(JsonFiledInfo.OBJECT_TYPE);
jsonFiledInfos.add(jfi);
}
} else {
jsonFiledInfo.setField(p);
jsonFiledInfo.setType(JsonFiledInfo.OBJECT_TYPE);
jsonFiledInfos.add(jsonFiledInfo);
}
}
}
return jsonFiledInfos;
}
private static String getByJsonFieldInfos(List<JsonFiledInfo> jsonFiledInfos, String jsonContent) {
String all = "*";
if (jsonFiledInfos == null || jsonFiledInfos.size() == 0||StringUtils.isEmpty(jsonContent)) {
return EMPTY_STRING;
}
try {
if (jsonFiledInfos.size() == 1) {
if (JsonFiledInfo.ARRAY_TYPE.equals(jsonFiledInfos.get(0).getType())) {
JSONArray jsonArray = JSONArray.parseArray(jsonContent);
if (all.equals(jsonFiledInfos.get(0).getField())) {
List<String> ss = new ArrayList<>();
for (int z = 0; z < jsonArray.size(); z++) {
ss.add(jsonArray.getString(z));
}
return list2String(ss, ",");
} else {
return jsonArray.getString(Integer.parseInt(jsonFiledInfos.get(0).getField()));
}
} else {
JSONObject jsonObject = JSONObject.parseObject(jsonContent);
return jsonObject.getString(jsonFiledInfos.get(0).getField());
}
}
if (jsonFiledInfos.size() > 1) {
JSON json = new JSONObject();
boolean curTypeObject;
boolean nextTypeObject;
for (int i = 0; i < jsonFiledInfos.size() - 1; i++) {
JsonFiledInfo curJsonFieldInfo = jsonFiledInfos.get(i);
JsonFiledInfo nextJsonFieldInfo = jsonFiledInfos.get(i + 1);
curTypeObject = curJsonFieldInfo.getType().equals(JsonFiledInfo.OBJECT_TYPE);
nextTypeObject = nextJsonFieldInfo.getType().equals(JsonFiledInfo.OBJECT_TYPE);
if (all.equals(curJsonFieldInfo.getField())) {
List<String> ss = new ArrayList<>();
JSONArray ja;
if (i == 0) {
ja = JSONArray.parseArray(jsonContent);
} else {
ja = (JSONArray) json;
}
for (int o = 0; o < ja.size(); o++) {
JsonFiledInfo jsonFiledInfo = new JsonFiledInfo();
jsonFiledInfo.setType(JsonFiledInfo.ARRAY_TYPE);
jsonFiledInfo.setField(String.valueOf(o));
List<JsonFiledInfo> jfs = Lists.newArrayList(jsonFiledInfos);
jfs.remove(i);
jfs.add(i, jsonFiledInfo);
ss.add(getByJsonFieldInfos(jfs, jsonContent));
}
return list2String(ss, ",");
}
if (i == 0) {
json = getJsonIfExpressSingle(jsonContent, curTypeObject, curJsonFieldInfo);
} else {
json = getJsonIfExpressMultiple(json, curTypeObject, nextTypeObject, curJsonFieldInfo);
}
}
try {
return ((JSONObject) json)
.getString(jsonFiledInfos.get(jsonFiledInfos.size() - 1).getField());
} catch (ClassCastException e) {
return ((JSONArray) json)
.getString(Integer.parseInt(jsonFiledInfos.get(jsonFiledInfos.size() - 1).getField()));
}
}
}catch (Exception e){
e.printStackTrace();
log.error("json取值异常:",e);
return null;
}
return EMPTY_STRING;
}
public static JSON getJsonIfExpressSingle(
String content, Boolean curTypeObject, JsonFiledInfo curJsonFiledInfo) {
if (curTypeObject) {
return JSONObject.parseObject(content).getJSONObject(curJsonFiledInfo.getField());
} else {
return JSONArray.parseArray(content)
.getJSONArray(Integer.parseInt(curJsonFiledInfo.getField()));
}
}
public static JSON getJsonIfExpressMultiple(
JSON json, Boolean curTypeObject, Boolean nextTypeObject, JsonFiledInfo curJsonFiledInfo) {
if (curTypeObject) {
JSONObject jsonObject = (JSONObject) json;
if (nextTypeObject) {
return jsonObject.getJSONObject(curJsonFiledInfo.getField());
} else {
return jsonObject.getJSONArray(curJsonFiledInfo.getField());
}
} else {
JSONArray jsonArray = (JSONArray) json;
if (nextTypeObject) {
return jsonArray.getJSONObject(Integer.valueOf(curJsonFiledInfo.getField()));
} else {
return jsonArray.getJSONArray(Integer.valueOf(curJsonFiledInfo.getField()));
}
}
}
public static String list2String(List<String> stringList, String delimiter) {
return Joiner.on(delimiter).skipNulls().join(stringList);
}
补充代码:
import lombok.Data;
@Data
public class JsonFiledInfo {
public static final String OBJECT_TYPE = "object";
public static final String ARRAY_TYPE = "array";
private String type = OBJECT_TYPE;
private String field;
}
完毕
OK,代码完毕,跑一下目标的案例就行了。