【转】JSON教程
JSON 是什么?
JSON 的全称是JavaScript Object Notation,是一种轻量级的数据交换格式。JSO
N 与XML 具有相同的特性,例如易于人编写和阅读,易于机器生成和解析。但是JSON 比
XML 数据传输的有效性要高出很多。JSON 完全独立与编程语言,使用文本格式保存。
JSON 数据有两种结构:
• Name-Value 对构成的集合,类似于Java 中的Map。
• Value 的有序列表,类似于Java 中的Array。
一个JSON 格式的数据示例:
{
"Name": "Apple",
"Expiry": "2007/10/11 13:54",
"Price": 3.99,
"Sizes": [
"Small",
"Medium",
"Large"
]
}
更多关于JSON 数据格式的说明参看JSON 官方网站:http://www.json.org(中文
内容参看:http://www.json.org/json-zh.html)
GWT与JSON
GWT 中支持的客户端服务器端方法调用和数据传递的标准格式是RPC。JSON 并不
是GWT支持的标准的数据传递格式。那么如何使用JSON 来作为GWT 的数据传递格式
呢?需要以下几步。
第一,引用HTTP 和JSON 支持。
第二,在客户端创建JSON 数据,提交到服务器
第三,在服务器上重写数据格式解析的代码,使之支持JSON 格式的数据
第四,在服务器上组织JSON 格式的数据,返回给客户端。
第五,客户端解析服务器传回的JSON 数据,正确的显示
引用HTTP和JSON支持
找到.gwt.xml 文件,在其中的
<inherits name='com.google.gwt.user.User'/>
在之后添加如下的内容:
<inherits name="com.google.gwt.json.JSON"/>
<inherits name="com.google.gwt.http.HTTP"/>
其中com.google.gwt.json.JSON 指的是要使用JSON,com.google.gwt.http.H
TTP 值得是通过HTTP 调用服务器上的服务方法。
客户端构造JSON数据
客户端需要使用com.google.gwt.json.client 包内的类来组装JSON 格式的数据,
数据格式如下:
组合一个简单的JSON 数据:
数据类型说明
JSONArray JSONValue 构成的数组类型
JSONBoolean JSON boolean 值
JSONException
访问JSON 结构的数据出错的情况下可以抛出此异
常
JSONNull JSON Null 根式的数据
JSONNumber JSON Number 类型的数据
JSONObject JSON Object 类型的数据
JSONParser
将String 格式的JSON 数据解析为JSONValue 类
型的数据
JSONString JSON String 类型的数据
JSONValue 所有JSON 类型值的超级类型
JSONObject input = new JSONObject();
JSONString value = new JSONString("mazhao");
input.put("name", value);
JSON 数据格式为:{name: "mazhao"}
组合一个包含数组类型的复杂JSON 数据:
JSONObject input = new JSONObject();
JSONString value = new JSONString("mazhao");
input.put("name", value);
JSONArray arrayValue = new JSONArray();
arrayValue.set(0, new JSONString("array item 0"));
arrayValue.set(1, new JSONString("array item 1"));
arrayValue.set(2, new JSONString("array item 2"));
input.put("array", arrayValue);
JSON 数据格式为:
{name: "mazhao",
array: {"array item 0", "array item 1", "array item 2"}}
注意上述的JSON 类型的数据,使用的都是com.google.gwt.json.client 包内的类
型。这些类型最终会被编译为JavaScript 执行。
服务端重写数据解析代码,支持JSON格式的数据
在服务器上,需要使用JSON Java 支持类才能将JSON 格式的数据转换为各种类型
的数据,当然也可以自己写一些解析用的代码。这里我们使用了www.json.org 上的代码
来完成。这组代码与com.google.gwt.json.client 的代码很相似,只是在org.json 包内
部。
怎么解析JSON 术诀呢?针对上述中的复杂的JSON 数据:
{name: "mazhao",
array: {"array item 0", "array item 1", "array item 2"}}
可以使用如下的方式解析:
JSONObject jsonObject = new JSONObject(payload);
String name = jsonObject.getString("name");
System.out.println("name is:" + name);
JSONArray jsonArray = jsonObject.getJSONArray("array");
for(int i = 0; i < jsonArray.length(); i++) {
System.out.println("item " + i + " :" + jsonArray.getString(i));
}
其中payload 指的是上述的JSON 格式的数据。
那么如何写GWT 的Service 来得到Payload 的数据呢?需要两点,第一,需要建立
一个Service 类,第二,覆盖父类的processCall 方法。
示例代码:
package com.jpleasure.gwt.json.server;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.jpleasure.gwt.json.client.HelloWorldService;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by IntelliJ IDEA.
* User: vaio
* Date: 2007-9-4
* Time: 22:08:31
* To change this template use File | Settings | File Templates.
*/
public class HelloWorldServiceImpl extends RemoteServiceServlet implements
HelloWorldService {
public String processCall(String payload) throws Serializat ionException {
try {
JSONObject jsonObject = new JSONObject(payload);
String name = jsonObject.getString("name");
System.out.println("name is:" + name);
JSONArray jsonArray = jsonObject.getJSONArray("array");
for(int i = 0; i < jsonArray.length(); i++) {
System.out.println("item " + i + " :" + jsonArray.getString(i));
}
} catch (JSONException e) {
e.printStackTrace(); //To change body of catch statement use File |
Settings | File Templates.
}
return "success";
}
}
在服务器上组织JSON格式的数据,返回给客户端
同上
客户端解析服务器传回的JSON数据,正确的显示
同上
Struts2返回json需要jsonplugin-0[1].25的
包
然后我们的配置文件中需要继承json-default
Java 代码
1. <?xml version="1.0" encoding="UTF-8" ?>
2. <!DOCTYPE struts PUBLIC
3. "-//Apache Software Foundation//DTD Struts Configuration 2.0//
EN"
4. "http://struts.apache.org/dtds/struts-2.0.dtd">
5.
6. <struts>
7.
8. <package name="com.act ion.testJson" extends="json-default" nam
espace="/" >
9. <action name="jsonUser" class="com.act ion.testJson.JsonAction
" method="testUser">
10. <result type="json"/>
11. </action>
12. <!-- Add actions here -->
13. </package>
14.</struts>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="com.act ion.testJson" extends="json-default"
namespace="/" >
<action name="jsonUser" class="com.act ion.testJson.JsonAction"
method="testUser">
<result type="json"/>
</action>
<!-- Add actions here -->
</package>
</struts>
然后我们的Action 中需要返回的json 信息需要加上注解
Java 代码
1. //pizza
2. package com.action.testJson;
3.
4. import java.util.ArrayList;
5. import java.util.List;
6.
7. import com.googlecode.jsonplugin.annotations.JSON;
8. import com.opensymphony.xwork2.ActionSupport;
9.
10.public class JsonAction extends ActionSupport {
11.
12. private static final long serialVersionUID = -
4082165361641669835L;
13.
14. Users user=new Users();
15. List userList=new ArrayList();
16.
17.
18. public String testUser(){
19. System.out.println("in the json Acton");
20. userInit();
21. userList.add(user);
22. return SUCCESS;
23. }
24.
25. public void userInit(){
26. user.setAge(1);
27. user.setName(" 张泽峰");
28. user.setPassword("nofengPassword");
29. }
30.
31. @JSON(name="userString")
32. public Users getUser() {
33. return user;
34. }
35.
36. @JSON(name="userList")
37. public List getUserList() {
38. return userList;
39. }
40.
41. public void setUser(Users user) {
42. this.user = user;
43. }
44.
45. public void setUserList(List userList) {
46. this.userList = userList;
47. }
48.
49.
50.}
JSON Plugin
的说明
Edit Page Browse Space Add Page Add News
Added by Musachy Barroso, last edited by ghostroller on Jul 04, 2008 (vie w change) SHOW COMMENT
Name JSON Plugin
Publisher Musachy Barroso
License Open Source (ASL2)
Version 0.30
Compatibility Struts 2.0.6 or later
Homepage http://code.google.com/p/jsonplugin/
Download http://code.google.com/p/jsonplugin/downloads/list
Overview
The JSON plugin provides a "json" result type that serializes actions into JSON. The serializa tion
process is recursive, meaning that the whole object graph, starting on the action class (base
class not included) will be serialized (root object can be customized using the "root" attribute).
If the interceptor is used, the action will be populated from the JSON content in the request,
these are the rules of the interceptor:
1. The "content-type" must be "application/json"
2. The JSON content must be well formed, see json.org for grammar.
3. Action must have a public "setter" method for fields that must be populated.
4. Supported types for population are: Primitives (int,long...String), Date, List, Map,
Primitive Arrays, Other class (more on this later), and Array of Other class.
5. Any object in JSON, that is to be populated inside a list, or a map, will be of type Map
(mapping from properties to values), any whole number will be of type Long, any
decimal number will be of type Double, and any array of type List.
Given this JSON string:
{
"doubleValue": 10.10,
"nestedBean": {
"name": "Mr Bean"
},
"list": ["A", 10, 20.20, {
"firstName": "El Zorro"
}],
"array": [10, 20]
}
The action must have a "setDoubleValue" method, taking either a "float" or a "double" argument
(the interceptor will convert the value to the right one). There must be a "setNestedBean"
whose argument type can be any class, that has a "setName" method taking as argument an
"String". There must be a "setList" method that takes a "List" as argument, that list will contain:
"A" (String), 10 (Long), 20.20 (Double), Map ("firstName" -> "El Zorro"). The "setArray"
method can take as parameter either a "List", or any numeric array.
Rating?
• 1
• 2
• 3
• 4
• 5
Installation
This plugin can be installed by copying the plugin jar into your application's /WEB-INF/lib
directory. No other files need to be copied or created.
To use maven, add this to your pom:
<dependencies>
...
<dependency>
<groupId>com.googlecode</groupId>
<artifactId>jsonplugin</artifactId>
<version>0.26</version>
</dependency>
...
</dependencies>
<repository>
<id>Maven Plugin Repository</id>
<url>http://struts2plugin-mavenrepo.
googlecode.com/svn/trunk/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
Customizing Serialization and Deserialization
Use the JSON annotation to customize the serializa tion/deserializa tion process. Available JSON
annotation fields:
Name Description Default Value Serialization Deserialization
name Customize field name empty yes no
serialize
Include in
serializa tion
true yes no
deserialize
Include in
deserializa tion
true no yes
Excluding properties
A comma-delimited list of regular expressions can be passed to the JSON Result and Interceptor,
properties matching any of these regular expressions will be ignored on the serializa tion process:
<!-- Result fragment -->
<result type="json">
<param name="excludeProperties">
login.password,
studentList.*\.sin
</param>
</result>
<!-- Interceptor fragment -->
<interceptor-ref name="json">
<param name="enableSMD">true</param>
<param name="excludeProperties">
login.password,
studentList.*\.sin
</param>
</interceptor-ref>
Including properties
A comma-delimited list of regular expressions can be passed to the JSON Result to restrict
which properties will be serialized. ONLY properties matching any of these regular expressions
will be included in the serialized output.
<!-- Result fragment -->
<result type="json">
<param name="includeProperties">
^entries\[\d+\]\.clientNumber,
format
Format used to
format/parse a Date
field
"yyyy-MM-dd'T'HH:mm:ss" yes yes
Note
Exclude property expressions take precedence over include property
expressions. That is, if you use include and exclude property expressions
on the same result, include property expressions will not be applied if an
exclude exclude property expression matches a property first.
^entries\[\d+\]\.scheduleNumber,
^entries\[\d+\]\.createUserId
</param>
</result>
Root Object
Use the "root" attribute(OGNL expression) to specify the root object to be serialized.
<result type="json">
<param name="root">
person.job
</param>
</result>
The "root" attribute(OGNL expression) can also be used on the interceptor to specify the object
that must be populated, make sure this object is not null.
<interceptor-ref name="json">
<param name="root">bean1.bean2</param>
</interceptor-ref>
Wrap with Comments
If the "wrapWithC omments" (false by default) attribute is set to true, the generated JSON is
wrapped with comments like:
/* {
"doubleVal": 10.10,
"nestedBean": {
"name": "Mr Bean"
},
"list": ["A", 10, 20.20, {
"firstName": "El Zorro"
}],
"array": [10, 20]
} */
wrapWithComments can turn safe JSON text into dangerous text. For
example,
["*/ alert('XSS'); /*"]
Thanks to Douglas Crockford for the tip!
This can be used to avoid potential Javascript Hijacks . To strip those comments use:
var responseObject = eval("("+data.substring(data.indexOf("\/\*")+2,
data.lastIndexOf("\*\/"))+")");
Base Classes
By default properties defined on base classes of the "root" object won't be serialized, to serialize
properties in all base classes (up to Object) set "ignoreHierarchy" to false in the JSON result:
<result type="json">
<param name="ignoreHierarchy">false</param>
</result>
Enumerations
By default, an Enum is serialized as a name=value pair where value = name().
public enum AnEnum {
ValueA,
ValueB
}
JSON: "myEnum":"ValueA"
Use the "enumAsBean" result parameter to serialize Enum's as a bean with a special property
_name with value name(). All properties of the enum are also serialized.
public enum AnEnum {
ValueA("A"),
ValueB("B");
private String val;
public AnEnum(val) {
this.val = val;
}
public getVal() {
return val;
}
}
JSON: myEnum: { "_name": "ValueA", "val": "A" }
Enable this parameter through struts.xml:
<result type="json">
<param name="enumAsBean">true</param>
</result>
Compressing the output.
Set the enableGZIP attribute to true to gzip the generated json response. The request must
include "gzip " in the "Accept-Encoding" header for this to work.
<result type="json">
<param name="enableGZIP" >true</param>
</result>
Example
Setup Action
This simple action has some fields:
Example:
import java.util.HashMap;
import java.util.Map;
import com.opensymphony.xwork2.Action;
public class JSONExample {
private String field1 = "str";
private int[] ints = {10, 20};
private Map map = new HashMap();
private String customName = "custom";
//'transient' fields are not serialized
private transient String field2;
//fields without getter method are not serialized
private String field3;
public String execute() {
map.put("John", "Galt");
return Action.SUCCESS;
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public int[] getInts() {
return ints;
}
public void setInts(int[] ints) {
this.ints = ints;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
@JSON(name="newName")
public String getCustomName() {
return this.customName;
}
}
Write the mapping for the action
1. Add the map inside a package that extends "json-default"
2. Add a result of type "json"
Example:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="example" extends="json-default">
<action name="JSONExample" class="example.JSONExample">
<result type="json"/>
</action>
</package>
</struts>
JSON example output
{
"field1" : "str",
"ints": [10, 20],
"map": {
"John":"Galt"
},
"newName": "custom"
}
JSON RPC
The json plugin can be used to execute action methods from javascript and return the output.
This feature was developed with Dojo in mind, so it uses Simple Method Definition to advertise
the remote service. Let's work it out with an example(useless as most examples).
First write the action:
package smd;
import com.googlecode.jsonplugin.annotations.SMDMethod;
import com.opensymphony.xwork2.Action;
public class SMDAction {
public String smd() {
return Action.SUCCESS;
}
@SMDMethod
public Bean doSomething(Bean bean, int quantity) {
bean.setPrice(quantity * 10);
return bean;
}
}
Methods that will be called remotely must be annotated with the SMDMethod annotation, for
security reasons. The method will take a bean object, modify its price and return it. The action
can be annotated with the SMD annotation to customize the generated SMD (more on that
soon), and parameters can be annotated with SMDMethodParameter. As you can see, we have a
"dummy", smd method. This method will be used to generate the Simple Method Definition (a
definition of all the services provided by this class), using the "json" result.
The bean class:
package smd;
public class Bean {
private String type;
private int price;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
The mapping:
<package name="RPC" namespace="/nodecorate" extends="json-default">
<action name="SMDAction" class="smd.SMDAction" method="smd">
<interceptor-ref name="json">
<param name="enableSMD">true</param>
</interceptor-ref>
<result type="json">
<param name="enableSMD">true</param>
</result>
</action>
</package>
Nothing special here, except that both the interceptor and the result must be applied to the
action, and "enableSMD" must be enabled for both.
Now the javascript code:
<s:url id="smdUrl" namespace="/nodecorate" action="SMDAction" />
<script type="text/javascript">
//load dojo RPC
dojo.require("dojo.rpc.*");
//create service object(proxy) using SMD (generated by the json
result)
var service = new dojo.rpc.JsonService("${smdUrl}");
//function called when remote method returns
var callback = function(bean) {
alert("Price for " + bean.type + " is " + bean.price);
};
//parameter
var bean = {type: "Mocca"};
//execute remote method
var defered = service.doSomething(bean, 5);
//attach callback to defered object
defered.addCallback(callback);
</script>
Dojo's JsonService will make a request to the action to load the SMD, which will return a JSON
object with the definition of the available remote methods, using that information Dojo creates a
"proxy" for those methods. Because of the asynchronous nature of the request, when the
method is executed, a deferred object is returned, to which a callback function can be attached.
The callback function will receive as a parameter the object returned from your action. That's it.
Proxied objects
(V0.20) As annotations are not inherited in Java, some user might experience problems while
trying to serialize objects that are proxied. eg. when you have attached AOP interceptors to your
action.
In this situation, the plugin will not detect the annotations on methods in your action.
To overcome this, set the "ignoreInterfaces" result parameter to false (true by default) to
request that the plugin inspects all interfaces and superclasses of the action for annotations on
the action's methods.
NOTE: This parameter should only be set to false if your action could be a proxy as there is a
performance cost caused by recursion through the interfaces.
<action name="contact" class="package.ContactAction" method="smd">
<interceptor-ref name="json">
<param name="enableSMD">true</param>
<param name="ignoreSMDMethodInterfaces">false</param>
</interceptor-ref>
<result type="json">
<param name="enableSMD">true</param>
<param name="ignoreInterfaces">false</param>
</result>
<interceptor-ref name="default"/>
</action>
在Struts 2中使用JSon ajax支持
来源: 作者: 发布时间:2007-12-19
JSON 插件提供了一种名为json 的ResultType,一旦为某个Action 指定了
一个类型为json 的Result,则该Result 无需映射到任何视图资源。因为JSON
插件会负责将Action 里的状态信息序列化成JSON 格式的数据,并将该数据返
回给客户端页面的JavaScript。
简单地说,JSON 插件允许我们在JavaScript 中异步调用Action,而且Action
不再需要使用视图资源来显示该Action 里的状态信息,而是由JSON 插件负责
将Action 里的状态信息返回给调用页面——通过这种方式,就能够完成Ajax
交互。
Struts2 提供了一种可插拔方式来管理插件,安装Struts2 的JSON 插件和安
装普通插件并没有太大的区别,相同只需要将Struts2 插件的JAR 文档复制到
Web 应用的WEB-INF/lib 路径下即可。
安装JSON 插件按如下步骤进行:
(1)登陆http://code.google.com/p/jsonplugin/downloads/list 站点,下载Struts2
的JSON 插件的最新版本,当前最新版本是0.7,我们能够下载该版本的JSON
插件。
(2)将下载到的jsonplugin-0.7.jar 文档复制到Web 应用的WEB-INF 路径
下,即可完成JSON 插件的安装。
实现Actio 逻辑
假设wo,en 输入页面中包含了三个表单域,这三个表单域对于三个请求参
数,因此应该使用Action 来封装这三个请求参数。三个表单域的name 分别为
field1 、field2 和field3 。
处理该请求的Action 类代码如下:
public class JSONExample
{
//封装请求参数的三个属性
private String field1;
private transient String field2;
private String field3;
//封装处理结果的属性
private int[] ints = {10, 20};
private Map map = new HashMap();
private String customName = "custom";
//三个请求参数对应的setter 和getter 方法
public String getField1()
{
return field1;
}
public void setField1(String field1)
{
this.field1 = field1;
} //此
处
省
略
了
field1 和
field2 两
个
字
段
的 setter 和
getter 方
法
...
//封装处理结果的属性的setter 和getter 方法
public int[] getInts()
{
return ints;
}
public void setInts(int[] ints)
{
this.ints = ints;
}
public Map getMap()
{
return map;
}
public void setMap(Map map)
{
this.map = map;
} //使
用
注
释
语
法
来
改
变
该
属
性
序
列
化
后
的
属
性
名
@JSON(name="newName")
public String getCustomName()
{
return this.customName;
}
public String execute()
{
map.put("na me", "yeek u");
return Action.SUCCESS;
}
}
在上面代码中,使用了JSON 注释,注释时指定了name 域,name 域指定
Action 属性被序列化成JSON 对象的属性名。除此之外,JSON 注释还支持如下
几个域:
serialize:配置是否序列化该属性
deserialize:配置是否反序列化该属性。
format:配置用于格式化输出、解析日期表单域的格式。例如"yyyy-MMdd'T'HH:
mm:ss"。
配置该Action 和配置普通Action 存在小小的区别,应该为该Action 配置
类型为json 的Result。而这个Result 无需配置任何视图资源。
配置该Action 的struts.xml 文档代码如下:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<consta nt name="struts.i18n.encod ing" value="UTF-8"/>
<package name="exa mple" extends="json-default">
<action name="JSONExample" class="lee.JSONExample">
<result type="json"/>
</action>
</package>
</struts>
在上面配置文档中有两个值得注意的地方:
第一个地方是配置struts.i18n.encod ing 常量时,不再是使用GBK 编码,而
是UTF-8 编码,这是因为Ajax 的POST 请求都是以UTF-8 的方式进行编码的。
第二个地方是配置包时,自己的包继承了json-default 包,而不再继承默认
的default 包,这是因为只有在该包下才有json 类型的Result。
JSON 的全称是JavaScript Object Notation,是一种轻量级的数据交换格式。JSO
N 与XML 具有相同的特性,例如易于人编写和阅读,易于机器生成和解析。但是JSON 比
XML 数据传输的有效性要高出很多。JSON 完全独立与编程语言,使用文本格式保存。
JSON 数据有两种结构:
• Name-Value 对构成的集合,类似于Java 中的Map。
• Value 的有序列表,类似于Java 中的Array。
一个JSON 格式的数据示例:
{
"Name": "Apple",
"Expiry": "2007/10/11 13:54",
"Price": 3.99,
"Sizes": [
"Small",
"Medium",
"Large"
]
}
更多关于JSON 数据格式的说明参看JSON 官方网站:http://www.json.org(中文
内容参看:http://www.json.org/json-zh.html)
GWT与JSON
GWT 中支持的客户端服务器端方法调用和数据传递的标准格式是RPC。JSON 并不
是GWT支持的标准的数据传递格式。那么如何使用JSON 来作为GWT 的数据传递格式
呢?需要以下几步。
第一,引用HTTP 和JSON 支持。
第二,在客户端创建JSON 数据,提交到服务器
第三,在服务器上重写数据格式解析的代码,使之支持JSON 格式的数据
第四,在服务器上组织JSON 格式的数据,返回给客户端。
第五,客户端解析服务器传回的JSON 数据,正确的显示
引用HTTP和JSON支持
找到.gwt.xml 文件,在其中的
<inherits name='com.google.gwt.user.User'/>
在之后添加如下的内容:
<inherits name="com.google.gwt.json.JSON"/>
<inherits name="com.google.gwt.http.HTTP"/>
其中com.google.gwt.json.JSON 指的是要使用JSON,com.google.gwt.http.H
TTP 值得是通过HTTP 调用服务器上的服务方法。
客户端构造JSON数据
客户端需要使用com.google.gwt.json.client 包内的类来组装JSON 格式的数据,
数据格式如下:
组合一个简单的JSON 数据:
数据类型说明
JSONArray JSONValue 构成的数组类型
JSONBoolean JSON boolean 值
JSONException
访问JSON 结构的数据出错的情况下可以抛出此异
常
JSONNull JSON Null 根式的数据
JSONNumber JSON Number 类型的数据
JSONObject JSON Object 类型的数据
JSONParser
将String 格式的JSON 数据解析为JSONValue 类
型的数据
JSONString JSON String 类型的数据
JSONValue 所有JSON 类型值的超级类型
JSONObject input = new JSONObject();
JSONString value = new JSONString("mazhao");
input.put("name", value);
JSON 数据格式为:{name: "mazhao"}
组合一个包含数组类型的复杂JSON 数据:
JSONObject input = new JSONObject();
JSONString value = new JSONString("mazhao");
input.put("name", value);
JSONArray arrayValue = new JSONArray();
arrayValue.set(0, new JSONString("array item 0"));
arrayValue.set(1, new JSONString("array item 1"));
arrayValue.set(2, new JSONString("array item 2"));
input.put("array", arrayValue);
JSON 数据格式为:
{name: "mazhao",
array: {"array item 0", "array item 1", "array item 2"}}
注意上述的JSON 类型的数据,使用的都是com.google.gwt.json.client 包内的类
型。这些类型最终会被编译为JavaScript 执行。
服务端重写数据解析代码,支持JSON格式的数据
在服务器上,需要使用JSON Java 支持类才能将JSON 格式的数据转换为各种类型
的数据,当然也可以自己写一些解析用的代码。这里我们使用了www.json.org 上的代码
来完成。这组代码与com.google.gwt.json.client 的代码很相似,只是在org.json 包内
部。
怎么解析JSON 术诀呢?针对上述中的复杂的JSON 数据:
{name: "mazhao",
array: {"array item 0", "array item 1", "array item 2"}}
可以使用如下的方式解析:
JSONObject jsonObject = new JSONObject(payload);
String name = jsonObject.getString("name");
System.out.println("name is:" + name);
JSONArray jsonArray = jsonObject.getJSONArray("array");
for(int i = 0; i < jsonArray.length(); i++) {
System.out.println("item " + i + " :" + jsonArray.getString(i));
}
其中payload 指的是上述的JSON 格式的数据。
那么如何写GWT 的Service 来得到Payload 的数据呢?需要两点,第一,需要建立
一个Service 类,第二,覆盖父类的processCall 方法。
示例代码:
package com.jpleasure.gwt.json.server;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.jpleasure.gwt.json.client.HelloWorldService;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by IntelliJ IDEA.
* User: vaio
* Date: 2007-9-4
* Time: 22:08:31
* To change this template use File | Settings | File Templates.
*/
public class HelloWorldServiceImpl extends RemoteServiceServlet implements
HelloWorldService {
public String processCall(String payload) throws Serializat ionException {
try {
JSONObject jsonObject = new JSONObject(payload);
String name = jsonObject.getString("name");
System.out.println("name is:" + name);
JSONArray jsonArray = jsonObject.getJSONArray("array");
for(int i = 0; i < jsonArray.length(); i++) {
System.out.println("item " + i + " :" + jsonArray.getString(i));
}
} catch (JSONException e) {
e.printStackTrace(); //To change body of catch statement use File |
Settings | File Templates.
}
return "success";
}
}
在服务器上组织JSON格式的数据,返回给客户端
同上
客户端解析服务器传回的JSON数据,正确的显示
同上
Struts2返回json需要jsonplugin-0[1].25的
包
然后我们的配置文件中需要继承json-default
Java 代码
1. <?xml version="1.0" encoding="UTF-8" ?>
2. <!DOCTYPE struts PUBLIC
3. "-//Apache Software Foundation//DTD Struts Configuration 2.0//
EN"
4. "http://struts.apache.org/dtds/struts-2.0.dtd">
5.
6. <struts>
7.
8. <package name="com.act ion.testJson" extends="json-default" nam
espace="/" >
9. <action name="jsonUser" class="com.act ion.testJson.JsonAction
" method="testUser">
10. <result type="json"/>
11. </action>
12. <!-- Add actions here -->
13. </package>
14.</struts>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="com.act ion.testJson" extends="json-default"
namespace="/" >
<action name="jsonUser" class="com.act ion.testJson.JsonAction"
method="testUser">
<result type="json"/>
</action>
<!-- Add actions here -->
</package>
</struts>
然后我们的Action 中需要返回的json 信息需要加上注解
Java 代码
1. //pizza
2. package com.action.testJson;
3.
4. import java.util.ArrayList;
5. import java.util.List;
6.
7. import com.googlecode.jsonplugin.annotations.JSON;
8. import com.opensymphony.xwork2.ActionSupport;
9.
10.public class JsonAction extends ActionSupport {
11.
12. private static final long serialVersionUID = -
4082165361641669835L;
13.
14. Users user=new Users();
15. List userList=new ArrayList();
16.
17.
18. public String testUser(){
19. System.out.println("in the json Acton");
20. userInit();
21. userList.add(user);
22. return SUCCESS;
23. }
24.
25. public void userInit(){
26. user.setAge(1);
27. user.setName(" 张泽峰");
28. user.setPassword("nofengPassword");
29. }
30.
31. @JSON(name="userString")
32. public Users getUser() {
33. return user;
34. }
35.
36. @JSON(name="userList")
37. public List getUserList() {
38. return userList;
39. }
40.
41. public void setUser(Users user) {
42. this.user = user;
43. }
44.
45. public void setUserList(List userList) {
46. this.userList = userList;
47. }
48.
49.
50.}
JSON Plugin
的说明
Edit Page Browse Space Add Page Add News
Added by Musachy Barroso, last edited by ghostroller on Jul 04, 2008 (vie w change) SHOW COMMENT
Name JSON Plugin
Publisher Musachy Barroso
License Open Source (ASL2)
Version 0.30
Compatibility Struts 2.0.6 or later
Homepage http://code.google.com/p/jsonplugin/
Download http://code.google.com/p/jsonplugin/downloads/list
Overview
The JSON plugin provides a "json" result type that serializes actions into JSON. The serializa tion
process is recursive, meaning that the whole object graph, starting on the action class (base
class not included) will be serialized (root object can be customized using the "root" attribute).
If the interceptor is used, the action will be populated from the JSON content in the request,
these are the rules of the interceptor:
1. The "content-type" must be "application/json"
2. The JSON content must be well formed, see json.org for grammar.
3. Action must have a public "setter" method for fields that must be populated.
4. Supported types for population are: Primitives (int,long...String), Date, List, Map,
Primitive Arrays, Other class (more on this later), and Array of Other class.
5. Any object in JSON, that is to be populated inside a list, or a map, will be of type Map
(mapping from properties to values), any whole number will be of type Long, any
decimal number will be of type Double, and any array of type List.
Given this JSON string:
{
"doubleValue": 10.10,
"nestedBean": {
"name": "Mr Bean"
},
"list": ["A", 10, 20.20, {
"firstName": "El Zorro"
}],
"array": [10, 20]
}
The action must have a "setDoubleValue" method, taking either a "float" or a "double" argument
(the interceptor will convert the value to the right one). There must be a "setNestedBean"
whose argument type can be any class, that has a "setName" method taking as argument an
"String". There must be a "setList" method that takes a "List" as argument, that list will contain:
"A" (String), 10 (Long), 20.20 (Double), Map ("firstName" -> "El Zorro"). The "setArray"
method can take as parameter either a "List", or any numeric array.
Rating?
• 1
• 2
• 3
• 4
• 5
Installation
This plugin can be installed by copying the plugin jar into your application's /WEB-INF/lib
directory. No other files need to be copied or created.
To use maven, add this to your pom:
<dependencies>
...
<dependency>
<groupId>com.googlecode</groupId>
<artifactId>jsonplugin</artifactId>
<version>0.26</version>
</dependency>
...
</dependencies>
<repository>
<id>Maven Plugin Repository</id>
<url>http://struts2plugin-mavenrepo.
googlecode.com/svn/trunk/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
Customizing Serialization and Deserialization
Use the JSON annotation to customize the serializa tion/deserializa tion process. Available JSON
annotation fields:
Name Description Default Value Serialization Deserialization
name Customize field name empty yes no
serialize
Include in
serializa tion
true yes no
deserialize
Include in
deserializa tion
true no yes
Excluding properties
A comma-delimited list of regular expressions can be passed to the JSON Result and Interceptor,
properties matching any of these regular expressions will be ignored on the serializa tion process:
<!-- Result fragment -->
<result type="json">
<param name="excludeProperties">
login.password,
studentList.*\.sin
</param>
</result>
<!-- Interceptor fragment -->
<interceptor-ref name="json">
<param name="enableSMD">true</param>
<param name="excludeProperties">
login.password,
studentList.*\.sin
</param>
</interceptor-ref>
Including properties
A comma-delimited list of regular expressions can be passed to the JSON Result to restrict
which properties will be serialized. ONLY properties matching any of these regular expressions
will be included in the serialized output.
<!-- Result fragment -->
<result type="json">
<param name="includeProperties">
^entries\[\d+\]\.clientNumber,
format
Format used to
format/parse a Date
field
"yyyy-MM-dd'T'HH:mm:ss" yes yes
Note
Exclude property expressions take precedence over include property
expressions. That is, if you use include and exclude property expressions
on the same result, include property expressions will not be applied if an
exclude exclude property expression matches a property first.
^entries\[\d+\]\.scheduleNumber,
^entries\[\d+\]\.createUserId
</param>
</result>
Root Object
Use the "root" attribute(OGNL expression) to specify the root object to be serialized.
<result type="json">
<param name="root">
person.job
</param>
</result>
The "root" attribute(OGNL expression) can also be used on the interceptor to specify the object
that must be populated, make sure this object is not null.
<interceptor-ref name="json">
<param name="root">bean1.bean2</param>
</interceptor-ref>
Wrap with Comments
If the "wrapWithC omments" (false by default) attribute is set to true, the generated JSON is
wrapped with comments like:
/* {
"doubleVal": 10.10,
"nestedBean": {
"name": "Mr Bean"
},
"list": ["A", 10, 20.20, {
"firstName": "El Zorro"
}],
"array": [10, 20]
} */
wrapWithComments can turn safe JSON text into dangerous text. For
example,
["*/ alert('XSS'); /*"]
Thanks to Douglas Crockford for the tip!
This can be used to avoid potential Javascript Hijacks . To strip those comments use:
var responseObject = eval("("+data.substring(data.indexOf("\/\*")+2,
data.lastIndexOf("\*\/"))+")");
Base Classes
By default properties defined on base classes of the "root" object won't be serialized, to serialize
properties in all base classes (up to Object) set "ignoreHierarchy" to false in the JSON result:
<result type="json">
<param name="ignoreHierarchy">false</param>
</result>
Enumerations
By default, an Enum is serialized as a name=value pair where value = name().
public enum AnEnum {
ValueA,
ValueB
}
JSON: "myEnum":"ValueA"
Use the "enumAsBean" result parameter to serialize Enum's as a bean with a special property
_name with value name(). All properties of the enum are also serialized.
public enum AnEnum {
ValueA("A"),
ValueB("B");
private String val;
public AnEnum(val) {
this.val = val;
}
public getVal() {
return val;
}
}
JSON: myEnum: { "_name": "ValueA", "val": "A" }
Enable this parameter through struts.xml:
<result type="json">
<param name="enumAsBean">true</param>
</result>
Compressing the output.
Set the enableGZIP attribute to true to gzip the generated json response. The request must
include "gzip " in the "Accept-Encoding" header for this to work.
<result type="json">
<param name="enableGZIP" >true</param>
</result>
Example
Setup Action
This simple action has some fields:
Example:
import java.util.HashMap;
import java.util.Map;
import com.opensymphony.xwork2.Action;
public class JSONExample {
private String field1 = "str";
private int[] ints = {10, 20};
private Map map = new HashMap();
private String customName = "custom";
//'transient' fields are not serialized
private transient String field2;
//fields without getter method are not serialized
private String field3;
public String execute() {
map.put("John", "Galt");
return Action.SUCCESS;
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public int[] getInts() {
return ints;
}
public void setInts(int[] ints) {
this.ints = ints;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
@JSON(name="newName")
public String getCustomName() {
return this.customName;
}
}
Write the mapping for the action
1. Add the map inside a package that extends "json-default"
2. Add a result of type "json"
Example:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="example" extends="json-default">
<action name="JSONExample" class="example.JSONExample">
<result type="json"/>
</action>
</package>
</struts>
JSON example output
{
"field1" : "str",
"ints": [10, 20],
"map": {
"John":"Galt"
},
"newName": "custom"
}
JSON RPC
The json plugin can be used to execute action methods from javascript and return the output.
This feature was developed with Dojo in mind, so it uses Simple Method Definition to advertise
the remote service. Let's work it out with an example(useless as most examples).
First write the action:
package smd;
import com.googlecode.jsonplugin.annotations.SMDMethod;
import com.opensymphony.xwork2.Action;
public class SMDAction {
public String smd() {
return Action.SUCCESS;
}
@SMDMethod
public Bean doSomething(Bean bean, int quantity) {
bean.setPrice(quantity * 10);
return bean;
}
}
Methods that will be called remotely must be annotated with the SMDMethod annotation, for
security reasons. The method will take a bean object, modify its price and return it. The action
can be annotated with the SMD annotation to customize the generated SMD (more on that
soon), and parameters can be annotated with SMDMethodParameter. As you can see, we have a
"dummy", smd method. This method will be used to generate the Simple Method Definition (a
definition of all the services provided by this class), using the "json" result.
The bean class:
package smd;
public class Bean {
private String type;
private int price;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
The mapping:
<package name="RPC" namespace="/nodecorate" extends="json-default">
<action name="SMDAction" class="smd.SMDAction" method="smd">
<interceptor-ref name="json">
<param name="enableSMD">true</param>
</interceptor-ref>
<result type="json">
<param name="enableSMD">true</param>
</result>
</action>
</package>
Nothing special here, except that both the interceptor and the result must be applied to the
action, and "enableSMD" must be enabled for both.
Now the javascript code:
<s:url id="smdUrl" namespace="/nodecorate" action="SMDAction" />
<script type="text/javascript">
//load dojo RPC
dojo.require("dojo.rpc.*");
//create service object(proxy) using SMD (generated by the json
result)
var service = new dojo.rpc.JsonService("${smdUrl}");
//function called when remote method returns
var callback = function(bean) {
alert("Price for " + bean.type + " is " + bean.price);
};
//parameter
var bean = {type: "Mocca"};
//execute remote method
var defered = service.doSomething(bean, 5);
//attach callback to defered object
defered.addCallback(callback);
</script>
Dojo's JsonService will make a request to the action to load the SMD, which will return a JSON
object with the definition of the available remote methods, using that information Dojo creates a
"proxy" for those methods. Because of the asynchronous nature of the request, when the
method is executed, a deferred object is returned, to which a callback function can be attached.
The callback function will receive as a parameter the object returned from your action. That's it.
Proxied objects
(V0.20) As annotations are not inherited in Java, some user might experience problems while
trying to serialize objects that are proxied. eg. when you have attached AOP interceptors to your
action.
In this situation, the plugin will not detect the annotations on methods in your action.
To overcome this, set the "ignoreInterfaces" result parameter to false (true by default) to
request that the plugin inspects all interfaces and superclasses of the action for annotations on
the action's methods.
NOTE: This parameter should only be set to false if your action could be a proxy as there is a
performance cost caused by recursion through the interfaces.
<action name="contact" class="package.ContactAction" method="smd">
<interceptor-ref name="json">
<param name="enableSMD">true</param>
<param name="ignoreSMDMethodInterfaces">false</param>
</interceptor-ref>
<result type="json">
<param name="enableSMD">true</param>
<param name="ignoreInterfaces">false</param>
</result>
<interceptor-ref name="default"/>
</action>
在Struts 2中使用JSon ajax支持
来源: 作者: 发布时间:2007-12-19
JSON 插件提供了一种名为json 的ResultType,一旦为某个Action 指定了
一个类型为json 的Result,则该Result 无需映射到任何视图资源。因为JSON
插件会负责将Action 里的状态信息序列化成JSON 格式的数据,并将该数据返
回给客户端页面的JavaScript。
简单地说,JSON 插件允许我们在JavaScript 中异步调用Action,而且Action
不再需要使用视图资源来显示该Action 里的状态信息,而是由JSON 插件负责
将Action 里的状态信息返回给调用页面——通过这种方式,就能够完成Ajax
交互。
Struts2 提供了一种可插拔方式来管理插件,安装Struts2 的JSON 插件和安
装普通插件并没有太大的区别,相同只需要将Struts2 插件的JAR 文档复制到
Web 应用的WEB-INF/lib 路径下即可。
安装JSON 插件按如下步骤进行:
(1)登陆http://code.google.com/p/jsonplugin/downloads/list 站点,下载Struts2
的JSON 插件的最新版本,当前最新版本是0.7,我们能够下载该版本的JSON
插件。
(2)将下载到的jsonplugin-0.7.jar 文档复制到Web 应用的WEB-INF 路径
下,即可完成JSON 插件的安装。
实现Actio 逻辑
假设wo,en 输入页面中包含了三个表单域,这三个表单域对于三个请求参
数,因此应该使用Action 来封装这三个请求参数。三个表单域的name 分别为
field1 、field2 和field3 。
处理该请求的Action 类代码如下:
public class JSONExample
{
//封装请求参数的三个属性
private String field1;
private transient String field2;
private String field3;
//封装处理结果的属性
private int[] ints = {10, 20};
private Map map = new HashMap();
private String customName = "custom";
//三个请求参数对应的setter 和getter 方法
public String getField1()
{
return field1;
}
public void setField1(String field1)
{
this.field1 = field1;
} //此
处
省
略
了
field1 和
field2 两
个
字
段
的 setter 和
getter 方
法
...
//封装处理结果的属性的setter 和getter 方法
public int[] getInts()
{
return ints;
}
public void setInts(int[] ints)
{
this.ints = ints;
}
public Map getMap()
{
return map;
}
public void setMap(Map map)
{
this.map = map;
} //使
用
注
释
语
法
来
改
变
该
属
性
序
列
化
后
的
属
性
名
@JSON(name="newName")
public String getCustomName()
{
return this.customName;
}
public String execute()
{
map.put("na me", "yeek u");
return Action.SUCCESS;
}
}
在上面代码中,使用了JSON 注释,注释时指定了name 域,name 域指定
Action 属性被序列化成JSON 对象的属性名。除此之外,JSON 注释还支持如下
几个域:
serialize:配置是否序列化该属性
deserialize:配置是否反序列化该属性。
format:配置用于格式化输出、解析日期表单域的格式。例如"yyyy-MMdd'T'HH:
mm:ss"。
配置该Action 和配置普通Action 存在小小的区别,应该为该Action 配置
类型为json 的Result。而这个Result 无需配置任何视图资源。
配置该Action 的struts.xml 文档代码如下:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<consta nt name="struts.i18n.encod ing" value="UTF-8"/>
<package name="exa mple" extends="json-default">
<action name="JSONExample" class="lee.JSONExample">
<result type="json"/>
</action>
</package>
</struts>
在上面配置文档中有两个值得注意的地方:
第一个地方是配置struts.i18n.encod ing 常量时,不再是使用GBK 编码,而
是UTF-8 编码,这是因为Ajax 的POST 请求都是以UTF-8 的方式进行编码的。
第二个地方是配置包时,自己的包继承了json-default 包,而不再继承默认
的default 包,这是因为只有在该包下才有json 类型的Result。