什麼是JSON
JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。它使得人們很容易的進行閱讀和編寫。同時也方便了機器進行解析和生成。
JSON採用完全獨立於程序語言的文本格式,但是也使用了類C語言的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。
這些特性使JSON成爲理想的數據交換語言。
json簡單說就是javascript中的對象和數組,所以這兩種結構就是對象和數組兩種結構,通過這兩種結構可以表示各種複雜的結構。
在JSON中可以使用的數據類型如上圖所示,JSON簡單來說就是數組與對象相互嵌套形成的一種數據結構。
其中對象是{}括起來的內容,以key-value形式來存儲數據,對應java中的Map。
數組是[]括起來的內容,字段值可以是字符串,數字,數組,對象,對應java中的List。
例:
[{"name":"塞爾達","age":"23"},{"name":"林克","age":"18"}]
這個JSON很明顯,是一個JSON數組,數組的字段值是對象。這個數組的size爲2。
layui動態表單----數據
首先我們來解析layui表單提交的JSON數據。
例:
[
{
"addressProvince":"1",
"overValue":"1",
"yearOverArea":"1",
"projectLevel":"1",
"companyName":"1",
"createYear":"2020",
"contractEnd":"2020-04-08",
"monthOverNumber":"1",
"yearDoingValue":"1",
"LAY_TABLE_INDEX":0,
"type":"",
"projectStatusName":"停工",
"layer":"1",
"addressDetail":"1",
"endImageProgress":"1",
"contractName":"1",
"state":0,
"subcompanyName":"山西一建集團有限公司",
"constructionArea":"1",
"addressCity":"1",
"formId":"",
"createMonthName":"1月",
"branchId":"169254",
"monthOverArea":"1",
"yearOverNumber":"1",
"branchName":"材料科",
"startDoingValue":"1",
"createMonth":"1",
"projectStatus":"1",
"monthDoingValue":"1",
"realEnd":"2020-04-10",
"contractPrice":"1",
"structureType":"1",
"createYearName":"2020年",
"addressDistrict":"1",
"realStart":"2020-04-09",
"contractStart":"2020-04-07",
"contractCode":"1"
},
{
"addressProvince":"1",
"overValue":"1",
"yearOverArea":"1",
"projectLevel":"1",
"companyName":"1",
"createYear":"2020",
"contractEnd":"2020-04-08",
"monthOverNumber":"1",
"yearDoingValue":"1",
"LAY_TABLE_INDEX":1,
"type":"",
"projectStatusName":"在施",
"layer":"1",
"addressDetail":"1",
"endImageProgress":"1",
"contractName":"1",
"state":0,
"subcompanyName":"山西一建集團有限公司",
"constructionArea":"1",
"addressCity":"1",
"formId":"",
"createMonthName":"1月",
"branchId":"169254",
"monthOverArea":"1",
"yearOverNumber":"1",
"branchName":"材料科",
"startDoingValue":"1",
"createMonth":"1",
"projectStatus":"0",
"monthDoingValue":"1",
"realEnd":"2020-04-10",
"contractPrice":"1",
"structureType":"1",
"createYearName":"2020年",
"addressDistrict":"1",
"realStart":"2020-04-09",
"contractStart":"2020-04-07",
"contractCode":"1"
}
]
看起來比較長,實際上就是一個簡單的數組內嵌套對象的JSON串,如下圖所示:
先貼出前端傳回這個JSON串的ajax
$.ajax({
type: 'post',//必須爲post
url: '/em/ext/api/test/create',
contentType : 'application/json;charset=utf-8', //設置請求頭信息
dataType:"json",//數據類型爲json
data: JSON.stringify(tableData),//通過函數進行轉換,將表單數據轉化爲JSON對象
success:function(res){
if(res.code=="M000000"){
layer.msg("保存成功");
}else{
layer.msg(res.info);
}
},
error:function(err){
console.log(err)
}
})
後臺Controller的參數:
public Map<String, Object> approval(@RequestBody String jsonStr){
}
注意這裏一定要加@RequestBody纔可接收json數據。
註解@RequestBody接收的參數是來自requestBody中,即請求體。因此前端的ajax方式必須爲post,get請求是沒有請求體的,因此該註解不適用。
這裏因爲是動態表單,所以是用的字符串來接收。若是非動態表單,可以使用實體類來接收數據。如果傳來的數據是對象類型,可以使用@RequestBody User user
來直接接收。如果傳來的對象是數組,數組內的元素是對象,則可使用@RequestBody List<User> user
來接收。
這裏我們解析動態表單,所以實體類內的元素是不確定的,因此用String來接收,之後再進行處理。
具體解析代碼如下:
public static List<String> parseJsonArray(String jsonStr){
JSONArray jArray = JSON.parseArray(jsonStr);
List<String> res = new ArrayList<>();
for(int i=0;i<jArray.size();i++){
JSONObject jsonObject = jArray.getJSONObject(i);
res.add(jsonObject.toString());
}
return res;
}
這個方法我們將json串中的多個對象拆分,存入List<String>中。
首先第一步,我們通過JSON.parseArray(jsonStr);
這個函數,將json字符串轉化爲JSONArray對象。
查看源碼我們可以看到,JSONArray類實現了List<Object>接口,因此他實現了List接口的方法。我們可以通過for循環進行遍歷,拿到他的具體某一個元素,這裏的元素是對象類型的json,因此我們調用它的getJSONObject(i);
方法,獲取它的JSON對象,最後再轉化爲字符串存入List中。後續如果需要操作,再通過JSON.parseObject(jsonStr);
方法將String類型的json解析成對象即可。
這裏我們再看一下JSONObject這個JSON對象。
可以看到它實現了Map<String,Object>接口,因此Map接口定義的方法,在JSONObject中均有實現。
由此我們可以印證之前所說,JSON中的數組就是Java中的LIst,JSON中的對象就是Java中的map。
layui動態表單----表頭
首先我們貼出layui動態表單渲染所需要的json串。
[
[
{
"field":"id",
"title":"建築業企業建築施工板塊完成情況月報",
"colspan":35
}
],
[
{
"field":"subcompanyName",
"title":"子集團名稱",
"rowspan":2
},
{
"field":"branchName",
"title":"分公司名稱",
"templet":"#branch",
"rowspan":2
},
{
"field":"companyName",
"edit":"text",
"title":"建設單位及單位工程名稱",
"rowspan":2
},
{
"field":"createYear",
"templet":"#year",
"title":"創建年份",
"rowspan":2
},
{
"field":"createMonth",
"templet":"#month",
"title":"創建月份",
"rowspan":2
},
{
"field":"contractName",
"edit":"text",
"title":"合同工程名稱",
"rowspan":2
},
{
"field":"contractCode",
"edit":"text",
"title":"合同編號",
"rowspan":2
},
{
"field":"contractPrice",
"edit":"text",
"title":"合同價(萬元)",
"rowspan":2
},
{
"title":"建設地址",
"colspan":4
},
{
"title":"合同工期",
"colspan":2
},
{
"title":"實際工期",
"colspan":2
},
{
"field":"structureType",
"edit":"text",
"title":"結構類型",
"rowspan":2
},
{
"field":"layer",
"edit":"text",
"title":"層數",
"rowspan":2
},
{
"field":"constructionArea",
"edit":"text",
"title":"施工面積(m²)",
"rowspan":2
},
{
"field":"projectLevel",
"edit":"text",
"title":"項目級別",
"rowspan":2
},
{
"field":"projectStatus",
"templet":"#projectStatus",
"title":"項目狀態",
"rowspan":2
},
{
"title":"竣工面積及竣工產值",
"colspan":5
},
{
"title":"施工產值(萬元)",
"colspan":3
},
{
"field":"endImageProgress",
"edit":"text",
"title":"期末形象進度",
"rowspan":2,
"width":100
},
{
"title":"操作",
"width":200,
"toolbar":"#toolbar",
"rowspan":2
}
],
[
{
"field":"addressProvince",
"edit":"text",
"title":"省"
},
{
"field":"addressCity",
"edit":"text",
"title":"市"
},
{
"field":"addressDistrict",
"edit":"text",
"title":"區/縣"
},
{
"field":"addressDetail",
"edit":"text",
"title":"詳細地址"
},
{
"field":"contractStart",
"templet":"#contractStart",
"title":"開工日期",
"rowspan":2
},
{
"field":"contractEnd",
"templet":"#contractEnd",
"title":"竣工日期",
"rowspan":2
},
{
"field":"realStart",
"templet":"#realStart",
"title":"開工日期",
"rowspan":2
},
{
"field":"realEnd",
"templet":"#realEnd",
"title":"竣工日期",
"rowspan":2
},
{
"field":"yearOverArea",
"edit":"text",
"title":"自年初累計_竣工面積(m2)"
},
{
"field":"yearOverNumber",
"edit":"text",
"title":"個數"
},
{
"field":"monthOverArea",
"edit":"text",
"title":"本月_竣工面積(m2)"
},
{
"field":"monthOverNumber",
"edit":"text",
"title":"個數"
},
{
"field":"overValue",
"edit":"text",
"title":"竣工產值(萬元)"
},
{
"field":"startDoingValue",
"edit":"text",
"title":"自開工累計"
},
{
"field":"yearDoingValue",
"edit":"text",
"title":"自年初累計完成"
},
{
"field":"monthDoingValue",
"edit":"text",
"title":"本月"
}
]
]
因爲這是一個三級表單的表頭,所以看上去很長,但實際上結構非常清晰。這個表頭實際頁面裏是這樣的。
整理後我們發現,JSON結構如下圖所示:
最外層是一個List,因爲表頭是三級,所以List內有3個元素,均爲List,我們繼續看內層List內部的結構:
如圖所示,內部是一個對象。也就是說,表頭的JSON結構要稍微複雜一些,嵌套關係是 外數組–內數組–對象。
這裏我們要做的是,找出表頭內所有含有field屬性的對象。因爲表單是動態的,所以我們拿到這些field也就相當於拿到了Map的Key,可以去表單數據的JSON串中獲取相應的數據。
代碼如下:
public static List<String> parseJsonHead(String jsonHead){
JSONArray jArray = JSON.parseArray(jsonHead);//將字符串轉化爲JSONArray對象,這裏是外層數組
List<Map<String, Object>> list = new ArrayList<>();
List<String> res = new ArrayList<>();
for(int i=0;i<jArray.size();i++){//循環,對外層數組進一步拆分
JSONArray jArr = jArray.getJSONArray(i);//得到內層數組對象
for(int j=0;j<jArr.size();j++){
JSONObject jsonObject = jArr.getJSONObject(j);//得到具體的每個對象,存入list
list.add(jsonObject);
}
}
list.forEach(v -> {//這裏我們遍歷得到的list,若field不爲空,則存入結果數組,最終我們得到存有字段名的數組List<String>
String field = (String)v.get("field");
if(field!=null){
res.add(field);
}
});
return res;
}
具體步驟見註釋。值得注意的是,由外層數組獲取內層數組的部分jArray.getJSONArray(i);
我們可以看到JSONArray類型也是可以調用getJSONArray這個api的,這正好與我們的理解相符,數組內部既可以是數組,也可以是對象。
Over~