使用JSON的方法
JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互。本文将快速讲解 JSON 格式,并通过代码示例演示如何分别在客户端和服务器端进行 JSON 格式数据的处理。
Json必需的包
commons-httpclient-3.1.jar
commons-lang-2.4.jar
commons-logging-1.1.1.jar
json-lib-2.2.3-jdk13.jar
ezmorph-1.0.6.jar
commons-collections-3.2.1.jar
以上包可以从
http://commons.apache.org/index.html
http://json-lib.sourceforge.net/
http://ezmorph.sourceforge.net/
中下载到。
出现java.lang.NoClassDefFoundError: net/sf/ezmorph/Morpher错误是因为没有导入ezmorph.jar文件或版本不对。
出现java.lang.NoClassDefFoundError: org/apache/commons/collections/map/ListOrderedMap错误是因为没有导入commons-collections.jar文件或版本不对。
Java代码转换成json代码
1. List集合转换成json代码
List list = new ArrayList(); list.add( "first" ); list.add( "second" ); JSONArray jsonArray2 = JSONArray.fromObject( list ); |
2. Map集合转换成json代码
Map map = new HashMap(); map.put("name", "json"); map.put("bool", Boolean.TRUE); map.put("int", new Integer(1)); map.put("arr", new String[] { "a", "b" }); map.put("func", "function(i){ return this.arr[i]; }"); JSONObject json = JSONObject.fromObject(map); |
3. Bean转换成json代码
JSONObject jsonObject = JSONObject.fromObject(new JsonBean()); |
4. 数组转换成json代码
boolean[] boolArray = new boolean[] { true, false, true }; JSONArray jsonArray1 = JSONArray.fromObject(boolArray); |
5. 一般数据转换成json代码
JSONArray jsonArray3 = JSONArray.fromObject("['json','is','easy']" ); |
6. beans转换成json代码
List list = new ArrayList(); JsonBean2 jb1 = new JsonBean2(); jb1.setCol(1); jb1.setRow(1); jb1.setValue("xx"); JsonBean2 jb2 = new JsonBean2(); jb2.setCol(2); jb2.setRow(2); jb2.setValue(""); list.add(jb1); list.add(jb2); JSONArray ja = JSONArray.fromObject(list); |
看了JSON的处理,对应存在特殊字符比如""的,怎么处理的?
用 \ 转义
关于 JSON 的Java库, Nutz 的 Json 解析器就非常好:
Java转换成Json:
1. Map<String,Object> map = new HashMap<String, Object>();
2. map.put("name", "Peter");
3. map.put("age", 21);
4. map.put("friends", null);
5. String result = Json.toJson(map);
Map<String,Object> map = new HashMap<String, Object>();
map.put("name", "Peter");
map.put("age", 21);
map.put("friends", null);
String result = Json.toJson(map);
这个时候会输出成:
1. {
2. age :21,
3. name :"Peter"
4. }
{
age :21,
name :"Peter"
}
会自动忽略掉值为空的字段.
Json转换成Java:
1. String json = "{age :21,name :\"Peter\"}";
2. map = Json.fromJson(HashMap.class, Lang.inr(json));
String json = "{age :21,name :\"Peter\"}";
map = Json.fromJson(HashMap.class, Lang.inr(json));
可以支持行注释,块注释, Json.fromJson(Class<T> type, Reader) 可以直接生成一个 Java 对象
详细的可以参见它的一个简单的手册:
http://code.google.com/p/nutz/downloads/detail?name=Nutz_Json_Book.pdf
我也是在用JSON,但不是像这样的动态生成js脚本,而是为了处理大批表格数据的读取问题,用struts(1.2)的action来生成json字符串,再用response.getWriter().write()输出到页面,ExtJS自然就是用Ext.data.JsonStore来读取了。这种方式的效率比较高,也达到了代码分离的目的,逻辑层和数据访问层根本无需暴露在web上,页面虽然是jsp,也无需使用<%%>或者struts标签。欢迎交流~
我先贴部分代码上来和大家交流一下,目前处于开发初期阶段,稍后我才做一个sample放上来。
1. /**
2. * 向浏览器输出JSON字符串
3. * @param response HttpServletResponse对象
4. * @param obj 任意对象,可以是List,也可以是单个对象
5. */
6. public void writeJsonString(HttpServletResponse response, Object obj) throws IOException {
7. if( obj == null ) {
8. this.exception = "obj参数为空";
9. logger.error(this.exception);
10. throw new NullPointerException(this.exception);
11. }
12.
13. JSONArray array = JSONArray.fromObject(obj);
14.
15. try {
16. String json = array.toString();
17. if( json.startsWith("[") ) {
18. json = json.substring(1);
19. }
20. if( json.endsWith("]") ) {
21. json = json.substring(0, json.length()-1);
22. }
23. response.setCharacterEncoding("utf-8");
24. response.getWriter().write(json);
25. } catch (IOException e) {
26. this.exception = "向浏览器输出JSON字符串时发生错误";
27. logger.error(this.exception);
28. logger.error(e);
29. throw new IOException(this.exception);
30. }
31. }
/**
* 向浏览器输出JSON字符串
* @param response HttpServletResponse对象
* @param obj 任意对象,可以是List,也可以是单个对象
*/
public void writeJsonString(HttpServletResponse response, Object obj) throws IOException {
if( obj == null ) {
this.exception = "obj参数为空";
logger.error(this.exception);
throw new NullPointerException(this.exception);
}
JSONArray array = JSONArray.fromObject(obj);
try {
String json = array.toString();
if( json.startsWith("[") ) {
json = json.substring(1);
}
if( json.endsWith("]") ) {
json = json.substring(0, json.length()-1);
}
response.setCharacterEncoding("utf-8");
response.getWriter().write(json);
} catch (IOException e) {
this.exception = "向浏览器输出JSON字符串时发生错误";
logger.error(this.exception);
logger.error(e);
throw new IOException(this.exception);
}
}
这里是js部分
1. var store = new Ext.data.JsonStore({
2. url: '../demo.do', //请大家根据实际情况修改action路径
3. root: 'data', //传回来的JSON字符串是HashMap生成的,data对应具体的数据集,一般是List对象
4. totalProperty: 'totalCount', //总记录数,整型
5. id: 'id',
6. fields: ['title', 'state', {name:'createDate', type: 'date'}, 'author', {name:'id', type:'int'}]
7. });
8. store.setDefaultSort('id', 'asc');
9. store.load({params:{start:0, limit:25}}); //传两个URL参数做分页处理
var store = new Ext.data.JsonStore({
url: '../demo.do', //请大家根据实际情况修改action路径
root: 'data', //传回来的JSON字符串是HashMap生成的,data对应具体的数据集,一般是List对象
totalProperty: 'totalCount', //总记录数,整型
id: 'id',
fields: ['title', 'state', {name:'createDate', type: 'date'}, 'author', {name:'id', type:'int'}]
});
store.setDefaultSort('id', 'asc');
store.load({params:{start:0, limit:25}}); //传两个URL参数做分页处理
还需要说明的是:需要json-lib-2.1-jdk15.jar, ezmorph-1.0.3.jar,到附件中取。
在学习JSON之前,当我在写大量JSP页面的时候,产生动态数据一般采用两种途径:
1.直接在页面中写java代码
2 采用各种标签代替
这两种用法的支持者都很多,但是我发现就算是采用标签也好,对于页面的重用还是无能为力,比如有几个页面都需要用到一个item数据,一个是管理用户页面,一个是订单页面。我们既要在管理用户的servlet写上setAttribute('item',item),也要在管理订单的servlet写上setAttribute('item',item);然后在页面上通过getAttribute()获得数据:
1. <%for(int i=0;i<item.length;++i){%>
2. html tag ...
3. <%}%>
<%for(int i=0;i<item.length;++i){%>
html tag ...
<%}%>
或者采用标签的形式:
1. <ww:iterator value="item">
2. html tag...
3. <ww:iterator>
<ww:iterator value="item">
html tag...
<ww:iterator>
很多时候我们会采用 <jsp:inclue page="common.jsp"/>来重用这样的页面,但这里有个问题,如果多个的页面样式不一样呢?如果数据不是很多呢,这样会产生很多页面碎片,实践已经证明,重用页面并不是一个好办法.
有时候我想,如果我能单独用一个action来提供输出数据,每个需要这些数据的页面页面都去获取这些数据,关于这些数据在页面如何渲染是页面的问题,这个action只提供数据,这样我们重用数据不是比重用页面好很多么?
但是之前的技术并不能支撑这样的实现,一个页面如何自己主动去访问它需要的数据呢?
答案是当然是通过AJAX技术.但今天我介绍的是另外一种技术JSON.
先简单的介绍一下JSON(虽然很多人已经知道),JSON JavaScirp Object Notion 可以看成一段javascript对象树,比如 user.id 表示的是user对象的id,如果对webwork或则是srtus2.0熟悉的朋友应该对此并不陌生,对象树可以嵌套对象,比如user.cat.age 表示user对象的成员cat的年龄。除了对象还可以嵌套数组方法user.cat[0].sayHello();
我们这样声明一个JSON:
1. var user = { id:’1’, name:’sanyun’};
2. alert(user.id) //输出1
3. user = { id:’1’, cat:{age:2,color:’white’ }};
4. alert(user.cat.age) //输出2
var user = { id:’1’, name:’sanyun’};
alert(user.id) //输出1
user = { id:’1’, cat:{age:2,color:’white’ }};
alert(user.cat.age) //输出2
但是JSON本身是不能和后端通信的,不过我们可以通过
1. <script type="text/javascript" src="后端资源"> </script>
<script type="text/javascript" src="后端资源"> </script>
来和服务器后端通信.
我们可以把它封装成一个方法:
1. function CallBack(model) {
2. this.model = model;
3. }
4. CallBack.init = function (url) {
5. var headElement = document.getElementsByTagName("head").item(0);
6. var scriptTag = document.createElement("script");
7. scriptTag.setAttribute("type", "text/javascript");
8. scriptTag.setAttribute("src", url);
9. headElement.appendChild(scriptTag);
10. };
function CallBack(model) {
this.model = model;
}
CallBack.init = function (url) {
var headElement = document.getElementsByTagName("head").item(0);
var scriptTag = document.createElement("script");
scriptTag.setAttribute("type", "text/javascript");
scriptTag.setAttribute("src", url);
headElement.appendChild(scriptTag);
};
不过需要注意的是采用这种方式后台MIME必须要设置为 html/Javascritp,当然你也可以轻松把这种方式替换成Ajax.
解析
通信之后我们需要做的是解析数据,一般来说,我们可以通过for in 简单的遍列JSON
1. //model表示后端产生的JSON
2. CallBack.update(model){
3. for(i in model){
4. var node =document.getElementByID(i);
5. if(node){
6. node.value = model[i];
7. }
8. }
9. }
//model表示后端产生的JSON
CallBack.update(model){
for(i in model){
var node =document.getElementByID(i);
if(node){
node.value = model[i];
}
}
}
后台
1. public class ShowType extends HttpServlet {
2.
3. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
4.
5. response.addHeader("Cache-Control", "no-cache"); //(1)
6. response.setContentType("HTML/JavaScript;charset=GBK");//(2)
7. PrintWriter out = response.getWriter();
8. String json = ” {name:'jiangyunpeng', status:'1',sex:'female'} ”//(3)
9. out.print("CallBack.update("+json+")"); //(4)
10. }
11. }
public class ShowType extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.addHeader("Cache-Control", "no-cache"); //(1)
response.setContentType("HTML/JavaScript;charset=GBK");//(2)
PrintWriter out = response.getWriter();
String json = ” {name:'jiangyunpeng', status:'1',sex:'female'} ”//(3)
out.print("CallBack.update("+json+")"); //(4)
}
}
(1)首先需要设置缓存为空
(2)然后MIME必须要设置为 html/Javascritp
(3)产生一段JSON,这里我们是手动产生的,可以采用JSON开源框架
(4)调用我们前面页面定义的JS函数
通过这样处理了之后我们的页面再也没有任何JAVA代码或者自定义标签了,他完全是一个HTML页面(当然这里为了演示,把解析JSON过程过于简单化了),他具有这些好处:
1.它是一个HTML,响应速度比JSP快
2.对于一些表单元素,比如checkbox,select,如果采用java代码会很繁琐,
1. function initCheckbox(){
2. if('<%=status%>'==1){ //这里有JAVA代码
3. document.getElementById('checkbox').checked = true;
4. }else{
5. document.getElementById('checkbox').checked = fasle;
6. }
7. }
function initCheckbox(){
if('<%=status%>'==1){ //这里有JAVA代码
document.getElementById('checkbox').checked = true;
}else{
document.getElementById('checkbox').checked = fasle;
}
}
但是如果采用JSON的话
1. function initCheckbox(){
2. if(status==1){ //这里只有JSON
3. document.getElementById('checkbox').checked = true;
4. }else{
5. document.getElementById('checkbox').checked = fasle;
6. }
7. }
function initCheckbox(){
if(status==1){ //这里只有JSON
document.getElementById('checkbox').checked = true;
}else{
document.getElementById('checkbox').checked = fasle;
}
}
二、把java的pojo类输出成json字符串
使用jackson的ObjectMapper 的writeValueAsString方法可以把pojo类输出成json字符串,代码如下:
package
com;
import
java.util.ArrayList;
import
java.util.HashMap;
import
java.util.List;
import
java.util.Map;
import
com.fasterxml.jackson.databind.ObjectMapper;
import
com.BaseObject;
public
class
JacksonJsonTest {
public
static
void
main(String[] args){
JacksonJsonTest jsonImple=
new
JacksonJsonTest();
try
{
ObjectMapper mapper =
new
ObjectMapper();
List dataList=
new
ArrayList();
Map<string,object> map =
new
HashMap<string, object=
""
>();
BaseObject object1=
new
BaseObject();
object1.setUserName(
"张三"
);
object1.setWeight(
65.5
);
object1.setHeight(
170
);
object1.setSex(
true
);
String[] score={
"80"
,
"90"
,
"95"
};
object1.setArray(score);
BaseObject object2=
new
BaseObject();
object2.setUserName(
"李四"
);
object2.setWeight(
75.5
);
object2.setHeight(
171
);
object2.setSex(
true
);
score=
new
String[
3
];
score[
0
]=
"65"
;
score[
1
]=
"68"
;
score[
2
]=
"75"
;
object2.setArray(score);
object1.setInnerObject(object2);
dataList.add(object1);
map.put(
"baseObject"
, dataList);
String json=mapper.writeValueAsString(object1);
System.out.println(json);
}
catch
(Exception ex){
}
}
}
</string,></string,object>
|
输出的结果如下:
{"userName":"王五","userCode":null,"weight":65.5,
"height":170,"sex":true,"array":["语文:85",
"数学:80","英语:95"],"innerObject":{"userName":"赵六",
"userCode":null,"weight":75.5,"height":171,"sex":true,
"array":["语文:65","数学:68","英语:75"],"innerObject":null}}