Java Web程序?qū)崿F(xiàn)返回JSON字符串的方法總結(jié)
基礎(chǔ)鋪墊
在java中,關(guān)于json的lib有很多,比如jackjson、fastjson、gson等等,本人都用過(guò),但是對(duì)于我等只需要讓java對(duì)象返回json字符串即可的程序員來(lái)說(shuō),還是顯得過(guò)于繁重。而且有些功能定制性很差,比如一個(gè)java對(duì)象的屬性為空時(shí),這些組件都不會(huì)輸出,于是本人在頁(yè)面循環(huán)遍歷列表對(duì)象時(shí),總是得判斷此屬性是否為undefined,這一點(diǎn)讓本人很不滿意。所以決定花點(diǎn)時(shí)間研究下到底是怎么回事。
但經(jīng)過(guò)一上午的細(xì)看,發(fā)現(xiàn)不管是fastjson還是gson都代碼都寫(xiě)得相當(dāng)?shù)膹?fù)雜,又沒(méi)什么相關(guān)的文檔與注釋,最后放棄了。于是自己又在www.json.com上找到了相對(duì)很簡(jiǎn)單的返回json的java包,這個(gè)lib只需要5個(gè)java類(lèi)即可運(yùn)行,正合我意。需要注意的是,官方的JSONArray這個(gè)東西并不支持javabean的直接轉(zhuǎn)換,比如List<User>這樣的東西是不能轉(zhuǎn)換的,必須要把它轉(zhuǎn)換成List<Map>這樣的格式,才能轉(zhuǎn)換,所以我對(duì)它進(jìn)行了改造。官方的文件有:
先介紹下基本用法。
處理基本的java對(duì)象使用JSONObject類(lèi),用法大體如下:
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對(duì)象,則采用JSONArray類(lèi),用法如下:
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("中國(guó)"); 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)); }
由上面的代碼可以看出,這個(gè)lib的用法相當(dāng)?shù)暮?jiǎn)單,不像什么gson之類(lèi)得新創(chuàng)建個(gè)對(duì)象,fastjson的API設(shè)計(jì)也有些不合理。上面的第二段代碼中,有個(gè)toString(2)表示按換行縮進(jìn)兩個(gè)空格的方式輸出。
上面只是介紹了基本用法,但這并不是自己想要的,自己想要的是怎么讓對(duì)象屬性為空時(shí)返回一個(gè)空字符串,而不是什么都不返回。雖然只有5個(gè)類(lèi),但本人還是花了兩三個(gè)小時(shí)的才找到地方,在JSONObject中有個(gè)叫populateMap的方法,在最后有小段代碼:
Object result = method.invoke(bean, (Object[])null); if (result != null) { this.map.put(key, wrap(result)); }
即當(dāng)調(diào)用get方法返回為null時(shí),就不輸出此屬性。當(dāng)然改起來(lái)就很簡(jiǎn)單了:
Object result = method.invoke(bean, (Object[])null); this.map.put(key, result==null?"":wrap(result));
這樣總算解決了本人想要解決的問(wèn)題。當(dāng)然這個(gè)lib是json官方自帶的,寫(xiě)得相當(dāng)?shù)暮?jiǎn)單,比較適合一次數(shù)據(jù)只有幾條或者幾十條的情況,如分頁(yè)顯示等。如果一次傳輸數(shù)據(jù)量比較大的話,可以考慮使用fastjson等。但個(gè)人覺(jué)得對(duì)于大多數(shù)場(chǎng)合來(lái)說(shuō),最需要的是可定制性。比如偶爾發(fā)現(xiàn)個(gè)某組件不能滿足的需要,結(jié)果此組件即無(wú)文檔也無(wú)注釋,代碼又比較難理解,基本上跟沒(méi)開(kāi)源差不多,那就沒(méi)什么意義了。
實(shí)例總結(jié)
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服務(wù)端返回JSON工具類(lèi) * 工具類(lèi)依賴FastJSON * 工具類(lèi)支持返回JSON和JSONP格式數(shù)據(jù) * @author accountwcx@qq.com * */ public class ResponseJsonUtils { /** * 默認(rèn)字符編碼 */ private static String encoding = "UTF-8"; /** * JSONP默認(rèn)的回調(diào)函數(shù) */ private static String callback = "callback"; /** * FastJSON的序列化設(shè)置 */ private static SerializerFeature[] features = new SerializerFeature[]{ //輸出Map中為Null的值 SerializerFeature.WriteMapNullValue, //如果Boolean對(duì)象為Null,則輸出為false SerializerFeature.WriteNullBooleanAsFalse, //如果List為Null,則輸出為[] SerializerFeature.WriteNullListAsEmpty, //如果Number為Null,則輸出為0 SerializerFeature.WriteNullNumberAsZero, //輸出Null字符串 SerializerFeature.WriteNullStringAsEmpty, //格式化輸出日期 SerializerFeature.WriteDateUseDateFormat }; /** * 把Java對(duì)象JSON序列化 * @param obj 需要JSON序列化的Java對(duì)象 * @return JSON字符串 */ private static String toJSONString(Object obj){ return JSON.toJSONString(obj, features); } /** * 返回JSON格式數(shù)據(jù) * @param response * @param data 待返回的Java對(duì)象 * @param encoding 返回JSON字符串的編碼格式 */ public static void json(HttpServletResponse response, Object data, String encoding){ //設(shè)置編碼格式 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格式數(shù)據(jù),使用默認(rèn)編碼 * @param response * @param data 待返回的Java對(duì)象 */ public static void json(HttpServletResponse response, Object data){ json(response, data, encoding); } /** * 返回JSONP數(shù)據(jù),使用默認(rèn)編碼和默認(rèn)回調(diào)函數(shù) * @param response * @param data JSONP數(shù)據(jù) */ public static void jsonp(HttpServletResponse response, Object data){ jsonp(response, callback, data, encoding); } /** * 返回JSONP數(shù)據(jù),使用默認(rèn)編碼 * @param response * @param callback JSONP回調(diào)函數(shù)名稱 * @param data JSONP數(shù)據(jù) */ public static void jsonp(HttpServletResponse response, String callback, Object data){ jsonp(response, callback, data, encoding); } /** * 返回JSONP數(shù)據(jù) * @param response * @param callback JSONP回調(diào)函數(shù)名稱 * @param data JSONP數(shù)據(jù) * @param encoding JSONP數(shù)據(jù)編碼 */ 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(");"); // 設(shè)置編碼格式 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; } }
/** * 在Servlet返回JSON數(shù)據(jù) */ @WebServlet("/json.do") public class JsonServlet extends HttpServlet { private static final long serialVersionUID = 7500835936131982864L; /** * 返回json格式數(shù)據(jù) */ 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("email", "accountwcx@qq.com"); data.put("age", 30); data.put("name", "csdn"); data.put("array", new int[]{1,2,3,4}); ResponseJsonUtils.json(response, data); } }
/** * Servlet返回JSONP格式數(shù)據(jù) */ @WebServlet("/jsonp.do") public class JsonpServlet extends HttpServlet { private static final long serialVersionUID = -8343408864035108293L; /** * 請(qǐng)求會(huì)發(fā)送callback參數(shù)作為回調(diào)函數(shù),如果沒(méi)有發(fā)送callback參數(shù)則使用默認(rèn)回調(diào)函數(shù) */ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //客戶端發(fā)送的回調(diào)函數(shù) String callback = request.getParameter("callback"); Map<String, Object> data = new HashMap<String, Object>(); data.put("date", new Date()); data.put("email", "accountwcx@qq.com"); data.put("age", 30); data.put("name", "csdn"); data.put("array", new int[]{1,2,3,4}); if(callback == null || callback.length() == 0){ //如果客戶端沒(méi)有發(fā)送回調(diào)函數(shù),則使用默認(rèn)的回調(diào)函數(shù) ResponseJsonUtils.jsonp(response, data); }else{ //使用客戶端的回調(diào)函數(shù) ResponseJsonUtils.jsonp(response, callback, data); } } }
/** * 在Struts2中返回JSON和JSONP */ public class JsonAction extends ActionSupport { private static final long serialVersionUID = 5391000845385666048L; /** * JSONP的回調(diào)函數(shù) */ 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("email", "accountwcx@qq.com"); 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("email", "accountwcx@qq.com"); data.put("age", 30); data.put("name", "csdn"); data.put("array", new int[]{1,2,3,4}); if(callback == null || callback.length() == 0){ //如果客戶端沒(méi)有發(fā)送回調(diào)函數(shù),則使用默認(rèn)的回調(diào)函數(shù) ResponseJsonUtils.jsonp(response, data); }else{ //使用客戶端的回調(diào)函數(shù) ResponseJsonUtils.jsonp(response, callback, data); } } public String getCallback() { return callback; } public void setCallback(String callback) { this.callback = callback; } }
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * Spring MVC返回JSON和JSONP數(shù)據(jù) */ @Controller @RequestMapping("/json") public class JsonController { /** * 返回JSON數(shù)據(jù) * @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("email", "accountwcx@qq.com"); data.put("age", 30); data.put("name", "csdn"); data.put("array", new int[]{1,2,3,4}); ResponseJsonUtils.json(response, data); } /** * 返回JSONP數(shù)據(jù) * @param callback JSONP的回調(diào)函數(shù) * @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("email", "accountwcx@qq.com"); data.put("age", 30); data.put("name", "csdn"); data.put("array", new int[]{1,2,3,4}); if(callback == null || callback.length() == 0){ //如果客戶端沒(méi)有發(fā)送回調(diào)函數(shù),則使用默認(rèn)的回調(diào)函數(shù) ResponseJsonUtils.jsonp(response, data); }else{ //使用客戶端的回調(diào)函數(shù) ResponseJsonUtils.jsonp(response, callback, data); } } }
相關(guān)文章
使用javassist動(dòng)態(tài)生成類(lèi)的配置代碼
Javassist它是一個(gè)用 Java 編輯字節(jié)碼的類(lèi)庫(kù),它使 Java 程序能夠在運(yùn)行時(shí)定義新類(lèi),并在 JVM 加載時(shí)修改類(lèi)文件,本文給大家介紹使用javassist動(dòng)態(tài)生成類(lèi)的實(shí)例代碼,感興趣的朋友一起看看吧2022-09-09淺談Java代碼的 微信長(zhǎng)鏈轉(zhuǎn)短鏈接口使用 post 請(qǐng)求封裝Json(實(shí)例)
下面小編就為大家?guī)?lái)一篇淺談Java代碼的 微信長(zhǎng)鏈轉(zhuǎn)短鏈接口使用 post 請(qǐng)求封裝Json(實(shí)例)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07Java利用Guava?Retry實(shí)現(xiàn)重處理
guava-retrying是谷歌的Guava庫(kù)的一個(gè)小擴(kuò)展,允許為任意函數(shù)調(diào)用創(chuàng)建可配置的重試策略,比如與正常運(yùn)行時(shí)間不穩(wěn)定的遠(yuǎn)程服務(wù)對(duì)話的函數(shù)調(diào)用。本文將利用其實(shí)現(xiàn)重處理,感興趣的可以了解一下2022-08-08解決spring 處理request.getInputStream()輸入流只能讀取一次問(wèn)題
這篇文章主要介紹了解決spring 處理request.getInputStream()輸入流只能讀取一次問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09Spring?BOOT?AOP基礎(chǔ)應(yīng)用教程
這篇文章主要介紹了Spring?BOOT?AOP的使用,文章從相關(guān)問(wèn)題展開(kāi)全文內(nèi)容詳情,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07IDEA2020.1啟動(dòng)SpringBoot項(xiàng)目出現(xiàn)java程序包:xxx不存在
這篇文章主要介紹了IDEA2020.1啟動(dòng)SpringBoot項(xiàng)目出現(xiàn)java程序包:xxx不存在,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06idea項(xiàng)目debug模式無(wú)法啟動(dòng)的解決
這篇文章主要介紹了idea項(xiàng)目debug模式無(wú)法啟動(dòng)的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02