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)讓本人很不滿(mǎn)意。所以決定花點(diǎn)時(shí)間研究下到底是怎么回事。
但經(jīng)過(guò)一上午的細(xì)看,發(fā)現(xiàn)不管是fastjson還是gson都代碼都寫(xiě)得相當(dāng)?shù)膹?fù)雜,又沒(méi)什么相關(guān)的文檔與注釋?zhuā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ù)量比較大的話(huà),可以考慮使用fastjson等。但個(gè)人覺(jué)得對(duì)于大多數(shù)場(chǎng)合來(lái)說(shuō),最需要的是可定制性。比如偶爾發(fā)現(xiàn)個(gè)某組件不能滿(mǎn)足的需要,結(jié)果此組件即無(wú)文檔也無(wú)注釋?zhuān)a又比較難理解,基本上跟沒(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)依賴(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ù)名稱(chēng)
* @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ù)名稱(chēng)
* @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 {
//客戶(hù)端發(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){
//如果客戶(hù)端沒(méi)有發(fā)送回調(diào)函數(shù),則使用默認(rèn)的回調(diào)函數(shù)
ResponseJsonUtils.jsonp(response, data);
}else{
//使用客戶(hù)端的回調(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){
//如果客戶(hù)端沒(méi)有發(fā)送回調(diào)函數(shù),則使用默認(rèn)的回調(diào)函數(shù)
ResponseJsonUtils.jsonp(response, data);
}else{
//使用客戶(hù)端的回調(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){
//如果客戶(hù)端沒(méi)有發(fā)送回調(diào)函數(shù),則使用默認(rèn)的回調(diào)函數(shù)
ResponseJsonUtils.jsonp(response, data);
}else{
//使用客戶(hù)端的回調(diào)函數(shù)
ResponseJsonUtils.jsonp(response, callback, data);
}
}
}
相關(guān)文章
SpringRunner和SpringJUnit4ClassRunner的區(qū)別及說(shuō)明
這篇文章主要介紹了SpringRunner和SpringJUnit4ClassRunner的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
Eclipse?IDE中如何設(shè)置JVM啟動(dòng)參數(shù)
這篇文章主要介紹了Eclipse?IDE中如何設(shè)置JVM啟動(dòng)參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
Java實(shí)現(xiàn)對(duì)象轉(zhuǎn)CSV格式
CSV是一種逗號(hào)分隔值格式的文件,一般用來(lái)存儲(chǔ)數(shù)據(jù)的純文本格式文件。Java對(duì)象轉(zhuǎn)CSV,有現(xiàn)成的工具包,commons-lang3 的ReflectionToStringBuilder 就可以簡(jiǎn)單的解決的對(duì)象轉(zhuǎn)CSV,快跟隨小編一起學(xué)習(xí)一下吧2022-06-06
關(guān)于Controller 層返回值的公共包裝類(lèi)的問(wèn)題
本文給大家介紹Controller 層返回值的公共包裝類(lèi)-避免每次都包裝一次返回-InitializingBean增強(qiáng),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-09-09
spring單元測(cè)試下模擬rabbitmq的實(shí)現(xiàn)
這篇文章主要介紹了spring單元測(cè)試下模擬rabbitmq的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
Java tomcat環(huán)境變量及idea配置解析
這篇文章主要介紹了Java tomcat環(huán)境變量及idea配置解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12
nacos-discovery包名層級(jí)問(wèn)題解決
這篇文章主要為大家介紹了nacos-discovery包名層級(jí)問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
Java線(xiàn)程中synchronized和volatile關(guān)鍵字的區(qū)別詳解
這篇文章主要介紹了Java線(xiàn)程中synchronized和volatile關(guān)鍵字的區(qū)別詳解,synchronzied既能夠保障可見(jiàn)性,又能保證原子性,而volatile只能保證可見(jiàn)性,無(wú)法保證原子性,volatile不需要加鎖,比synchronized更輕量級(jí),不會(huì)阻塞線(xiàn)程,需要的朋友可以參考下2024-01-01

