SpringMVC 將複雜物件以json格式返回前端
環境
SpringMVC 4.3.5
Jackson 2.6.5
複雜物件描述
涵蓋列表, 而列表裡面的每一個也都是物件
返回json資料如下:
{
"nodes": [
{"id": "Myriel", "group": 1},
{"id": "Napoleon", "group": 1},
{"id": "Mlle.Baptistine", "group": 1},
{"id": "Mme.Magloire", "group": 1},
{"id": "CountessdeLo", "group": 1},
{"id": "Geborand" , "group": 1},
{"id": "Champtercier", "group": 1}
],
"links": [
{"source": "Napoleon", "target": "Myriel", "value": 1},
{"source": "Mlle.Baptistine", "target": "Myriel", "value": 8},
{"source": "Mme.Magloire", "target": "Myriel", "value": 10},
{"source": "Mme.Magloire", "target ": "Mlle.Baptistine", "value": 6}
]
}
步驟
1. json中的nodes列表裡的是的為GNode物件, links列表裡的物件為GLink物件
[Tips] 對於物件裡的每一個屬性, 均需要編寫getter方法, 否則會出現如下錯誤
HTTP Status 500 - Could not write content: No serializer found for class com.iaso.antibiotic.json.GLink and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: java.util.HashMap[“links”]->java.util.ArrayList[0]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class com.iaso.antibiotic.json.GLink and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: java.util.HashMap[“links”]->java.util.ArrayList[0])
GNode.java
public class GNode{
/**
* 節點類
* 涵蓋節點基本資訊:
* @id:初步定為藥物名稱
* @infos:所涵蓋資訊因節點型別而定
* - Antibiotic(name, type, description, drug_indication)
* - Bacteria(name, type, description)
* - Situtation(name)
* @group:決定節點顏色,不同類別應該有不同的顏色
*/
private String id;
private String infos;
private int group;
public GNode(String id, int group) {
this.id = id;
this.group = group;
}
public String getInfos() {
return infos;
}
public void setInfos(String infos) {
this.infos = infos;
}
public String getId() {
return id;
}
public int getGroup() {
return group;
}
}
GLink.java
public class GLink {
/**
* 連線線類
* 涵蓋連線的基本資訊:
* @source:只有一個,即為查詢的節點
* @target
* @value=1
*/
private String source;
private String target;
private int value;
public GLink(String source, String target, int value) {
this.source = source;
this.target = target;
this.value = value;
}
public GLink(String source, String target) {
this.source = source;
this.target = target;
this.value = 1;
}
public String getSource() {
return source;
}
public String getTarget() {
return target;
}
public int getValue() {
return value;
}
}
2. 設定前端資料請求格式
這裡以提交表格為例, 注意這一句: datatype: "application/json
<form id="searchForm">
<input type="text" id="keywords" name="keywords" class="form-control input-lg" placeholder="搜尋......" value="AmBisome">
<input type="button" class="btn btn-default btn-lg" onclick="clickButton()" value="search">
<input type="hidden" id="graph" name="graph" value="IASO">
</form>
<script type="text/javascript">
function clickButton() {
$.ajax({
type: "POST",
url: "/search",
data: $("#searchForm").serialize(),
datatype: "application/json",
error: function(error) {
console.log(error.toString());
},
success: function(data){
console.log("Successfully accept.");
console.log(data.toString());
});
};
</script>
3. Controller的編寫
注意這一句 @ResponseBody
@Controller
public class SearchController {
// 搜尋欄:搜尋領域graph,搜尋關鍵詞keywords
@RequestMapping(name = "/search", method = RequestMethod.POST)
@ResponseBody
public HashMap<String, Object> testGraph(String keywords, String graph) {
HashMap<String, Object> map = new HashMap<String, Object>();
GNode gNode1 = new GNode("One", 1);
GNode gNode2 = new GNode("Two", 2);
GNode gNode = new GNode("Source", 0);
ArrayList<GNode> node_list = new ArrayList<GNode>();
node_list.add(gNode);
node_list.add(gNode1);
node_list.add(gNode2);
map.put("nodes", node_list);
GLink gLink1 = new GLink("Source", "One");
GLink gLink2 = new GLink("Source", "Two");
ArrayList<GLink> link_list = new ArrayList<GLink>();
link_list.add(gLink1);
link_list.add(gLink2);
map.put("links", link_list);
return map;
}
思考
其實按照本次部落格的題目的話, 按道理返回的應該是把整個json格式的資料看成一個物件, 這裡假設是Graph, Graph含有兩個性質: nodes和 links, 前者的資料型別應該是ArrayList<GNode>
, 後者的資料格式為ArrayList<GLink>
. 那麼就真的是”將複雜物件轉為json返回給前端了”.
新增Graph類
Graph.java
public class Graph {
private ArrayList<GNode> nodes = new ArrayList<GNode>();
private ArrayList<GLink> links = new ArrayList<GLink>();
private String keyword;
private String Graph;
public Graph(String keyword, String graph) {
this.keyword = keyword;
Graph = graph;
}
public Graph(String keyword) {
this.keyword = keyword;
}
public Graph() {
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public void setGraph(String graph) {
Graph = graph;
}
public ArrayList<GLink> getLinks() {
return links;
}
public void setLinks(ArrayList<GLink> links) {
this.links = links;
}
public String getKeyword() {
return keyword;
}
public String getGraph() {
return Graph;
}
public ArrayList<GNode> getNodes() {
return nodes;
}
public void setNodes(ArrayList<GNode> nodes) {
this.nodes = nodes;
}
}
修改Controller中的testGraph
注意此時的返回物件是Graph
// parse 複雜物件(內含ArrayList<物件>) into json, 但是這種做法不符合POJO原則(物件套物件)
@RequestMapping(name = "/search", method = RequestMethod.POST)
@ResponseBody
public Graph testGraph(String keywords, String graph) {
HashMap<String, Object> map = new HashMap<String, Object>();
Graph test_graph = new Graph();
GNode gNode1 = new GNode("One", 1);
GNode gNode2 = new GNode("Two", 2);
GNode gNode = new GNode("Source", 0);
ArrayList<GNode> node_list = new ArrayList<GNode>();
node_list.add(gNode);
node_list.add(gNode1);
node_list.add(gNode2);
test_graph.setNodes(node_list);
GLink gLink1 = new GLink("Source", "One");
GLink gLink2 = new GLink("Source", "Two");
ArrayList<GLink> link_list = new ArrayList<GLink>();
link_list.add(gLink1);
link_list.add(gLink2);
test_graph.setLinks(link_list);
return test_graph;
}
正如我在註釋中所言, 這麼做是不符合POJO的設計原則噠~
所以還是推薦第一做法哈~