1. 程式人生 > >SpringMVC 將複雜物件以json格式返回前端

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的設計原則噠~
所以還是推薦第一做法哈~