基礎鋪墊
在java中,關于json的lib有很多,比如jackjson、fastjson、gson等等,本人都用過,但是對于我等只需要讓java對象返回json字符串即可的程序員來說,還是顯得過于繁重。而且有些功能定制性很差,比如一個java對象的屬性為空時,這些組件都不會輸出,于是本人在頁面循環遍歷列表對象時,總是得判斷此屬性是否為undefined,這一點讓本人很不滿意。所以決定花點時間研究下到底是怎么回事。
但經過一上午的細看,發現不管是fastjson還是gson都代碼都寫得相當的復雜,又沒什么相關的文檔與注釋,最后放棄了。于是自己又在www.json.com上找到了相對很簡單的返回json的java包,這個lib只需要5個java類即可運行,正合我意。需要注意的是,官方的JSONArray這個東西并不支持javabean的直接轉換,比如List<User>這樣的東西是不能轉換的,必須要把它轉換成List<Map>這樣的格式,才能轉換,所以我對它進行了改造。官方的文件有:
先介紹下基本用法。
處理基本的java對象使用JSONObject類,用法大體如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public void testMap(){ Map<String,Object> map = new HashMap<String,Object>(); map.put( "name" , "qiu" ); map.put( "password" , "123" ); map.put( "address" , "china" ); User user = new User(); user.setUserName( "qiuqiu" ); user.setPassword( "123456" ); user.getTels().add( "1234444556677" ); user.getTels().add( "6893493458585" ); map.put( "user" , user); JSONObject json = new JSONObject(map); System.out.println(json.toString()); } |
如果是collection對象,則采用JSONArray類,用法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public void testList() throws JSONException{ List<User> list = new ArrayList<User>(); User user = new User(); user.setUserName( "qiuqiu" ); user.setPassword( "123456" ); user.getTels().add( "1234444556677" ); user.getTels().add( "6893493458585" ); User user2 = new User(); user2.setUserName( "中國" ); user2.getTels().add( "1234444556677" ); user2.getTels().add( "6893493458585" ); list.add(user); list.add(user2); JSONArray json = new JSONArray(list); System.out.println(json.toString( 2 )); } |
由上面的代碼可以看出,這個lib的用法相當的簡單,不像什么gson之類得新創建個對象,fastjson的API設計也有些不合理。上面的第二段代碼中,有個toString(2)表示按換行縮進兩個空格的方式輸出。
上面只是介紹了基本用法,但這并不是自己想要的,自己想要的是怎么讓對象屬性為空時返回一個空字符串,而不是什么都不返回。雖然只有5個類,但本人還是花了兩三個小時的才找到地方,在JSONObject中有個叫populateMap的方法,在最后有小段代碼:
1
2
3
4
|
Object result = method.invoke(bean, (Object[]) null ); if (result != null ) { this .map.put(key, wrap(result)); } |
即當調用get方法返回為null時,就不輸出此屬性。當然改起來就很簡單了:
1
2
|
Object result = method.invoke(bean, (Object[]) null ); this .map.put(key, result== null ? "" :wrap(result)); |
這樣總算解決了本人想要解決的問題。當然這個lib是json官方自帶的,寫得相當的簡單,比較適合一次數據只有幾條或者幾十條的情況,如分頁顯示等。如果一次傳輸數據量比較大的話,可以考慮使用fastjson等。但個人覺得對于大多數場合來說,最需要的是可定制性。比如偶爾發現個某組件不能滿足的需要,結果此組件即無文檔也無注釋,代碼又比較難理解,基本上跟沒開源差不多,那就沒什么意義了。
實例總結
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServletResponse; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; /** * * Web服務端返回JSON工具類 * 工具類依賴FastJSON * 工具類支持返回JSON和JSONP格式數據 * @author [email protected] * */ public class ResponseJsonUtils { /** * 默認字符編碼 */ private static String encoding = "UTF-8" ; /** * JSONP默認的回調函數 */ private static String callback = "callback" ; /** * FastJSON的序列化設置 */ private static SerializerFeature[] features = new SerializerFeature[]{ //輸出Map中為Null的值 SerializerFeature.WriteMapNullValue, //如果Boolean對象為Null,則輸出為false SerializerFeature.WriteNullBooleanAsFalse, //如果List為Null,則輸出為[] SerializerFeature.WriteNullListAsEmpty, //如果Number為Null,則輸出為0 SerializerFeature.WriteNullNumberAsZero, //輸出Null字符串 SerializerFeature.WriteNullStringAsEmpty, //格式化輸出日期 SerializerFeature.WriteDateUseDateFormat }; /** * 把Java對象JSON序列化 * @param obj 需要JSON序列化的Java對象 * @return JSON字符串 */ private static String toJSONString(Object obj){ return JSON.toJSONString(obj, features); } /** * 返回JSON格式數據 * @param response * @param data 待返回的Java對象 * @param encoding 返回JSON字符串的編碼格式 */ public static void json(HttpServletResponse response, Object data, String encoding){ //設置編碼格式 response.setContentType( "text/plain;charset=" + encoding); response.setCharacterEncoding(encoding); PrintWriter out = null ; try { out = response.getWriter(); out.write(toJSONString(data)); out.flush(); } catch (IOException e){ e.printStackTrace(); } } /** * 返回JSON格式數據,使用默認編碼 * @param response * @param data 待返回的Java對象 */ public static void json(HttpServletResponse response, Object data){ json(response, data, encoding); } /** * 返回JSONP數據,使用默認編碼和默認回調函數 * @param response * @param data JSONP數據 */ public static void jsonp(HttpServletResponse response, Object data){ jsonp(response, callback, data, encoding); } /** * 返回JSONP數據,使用默認編碼 * @param response * @param callback JSONP回調函數名稱 * @param data JSONP數據 */ public static void jsonp(HttpServletResponse response, String callback, Object data){ jsonp(response, callback, data, encoding); } /** * 返回JSONP數據 * @param response * @param callback JSONP回調函數名稱 * @param data JSONP數據 * @param encoding JSONP數據編碼 */ public static void jsonp(HttpServletResponse response, String callback, Object data, String encoding){ StringBuffer sb = new StringBuffer(callback); sb.append( "(" ); sb.append(toJSONString(data)); sb.append( ");" ); // 設置編碼格式 response.setContentType( "text/plain;charset=" + encoding); response.setCharacterEncoding(encoding); PrintWriter out = null ; try { out = response.getWriter(); out.write(sb.toString()); out.flush(); } catch (IOException e) { e.printStackTrace(); } } public static String getEncoding() { return encoding; } public static void setEncoding(String encoding) { ResponseJsonUtils.encoding = encoding; } public static String getCallback() { return callback; } public static void setCallback(String callback) { ResponseJsonUtils.callback = callback; } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/** * 在Servlet返回JSON數據 */ @WebServlet ( "/json.do" ) public class JsonServlet extends HttpServlet { private static final long serialVersionUID = 7500835936131982864L; /** * 返回json格式數據 */ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Map<String, Object> data = new HashMap<String, Object>(); data.put( "date" , new Date()); data.put( "age" , 30 ); data.put( "name" , "csdn" ); data.put( "array" , new int []{ 1 , 2 , 3 , 4 }); ResponseJsonUtils.json(response, data); } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
/** * Servlet返回JSONP格式數據 */ @WebServlet ( "/jsonp.do" ) public class JsonpServlet extends HttpServlet { private static final long serialVersionUID = -8343408864035108293L; /** * 請求會發送callback參數作為回調函數,如果沒有發送callback參數則使用默認回調函數 */ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //客戶端發送的回調函數 String callback = request.getParameter( "callback" ); Map<String, Object> data = new HashMap<String, Object>(); data.put( "date" , new Date()); data.put( "age" , 30 ); data.put( "name" , "csdn" ); data.put( "array" , new int []{ 1 , 2 , 3 , 4 }); if (callback == null || callback.length() == 0 ){ //如果客戶端沒有發送回調函數,則使用默認的回調函數 ResponseJsonUtils.jsonp(response, data); } else { //使用客戶端的回調函數 ResponseJsonUtils.jsonp(response, callback, data); } } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
/** * 在Struts2中返回JSON和JSONP */ public class JsonAction extends ActionSupport { private static final long serialVersionUID = 5391000845385666048L; /** * JSONP的回調函數 */ private String callback; /** * 返回JSON */ public void json(){ HttpServletResponse response = ServletActionContext.getResponse(); Map<String, Object> data = new HashMap<String, Object>(); data.put( "date" , new Date()); data.put( "age" , 30 ); data.put( "name" , "csdn" ); data.put( "array" , new int []{ 1 , 2 , 3 , 4 }); ResponseJsonUtils.json(response, data); } /** * 返回JSONP */ public void jsonp(){ HttpServletResponse response = ServletActionContext.getResponse(); Map<String, Object> data = new HashMap<String, Object>(); data.put( "date" , new Date()); data.put( "age" , 30 ); data.put( "name" , "csdn" ); data.put( "array" , new int []{ 1 , 2 , 3 , 4 }); if (callback == null || callback.length() == 0 ){ //如果客戶端沒有發送回調函數,則使用默認的回調函數 ResponseJsonUtils.jsonp(response, data); } else { //使用客戶端的回調函數 ResponseJsonUtils.jsonp(response, callback, data); } } public String getCallback() { return callback; } public void setCallback(String callback) { this .callback = callback; } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * Spring MVC返回JSON和JSONP數據 */ @Controller @RequestMapping ( "/json" ) public class JsonController { /** * 返回JSON數據 * @param request * @param response */ @RequestMapping ( "/json.do" ) public void json(HttpServletRequest request, HttpServletResponse response){ Map<String, Object> data = new HashMap<String, Object>(); data.put( "date" , new Date()); data.put( "age" , 30 ); data.put( "name" , "csdn" ); data.put( "array" , new int []{ 1 , 2 , 3 , 4 }); ResponseJsonUtils.json(response, data); } /** * 返回JSONP數據 * @param callback JSONP的回調函數 * @param request * @param response */ @RequestMapping ( "/jsonp.do" ) public void json(String callback, HttpServletRequest request, HttpServletResponse response){ Map<String, Object> data = new HashMap<String, Object>(); data.put( "date" , new Date()); data.put( "age" , 30 ); data.put( "name" , "csdn" ); data.put( "array" , new int []{ 1 , 2 , 3 , 4 }); if (callback == null || callback.length() == 0 ){ //如果客戶端沒有發送回調函數,則使用默認的回調函數 ResponseJsonUtils.jsonp(response, data); } else { //使用客戶端的回調函數 ResponseJsonUtils.jsonp(response, callback, data); } } } |