JSON

来源:互联网 发布:文章演技 知乎 编辑:程序博客网 时间:2024/05/22 17:43

JSON 的含义?

JSON的全称是JavaScript Object Notation,是一种轻量级的数据交换格式。JSONXML具有相同的特性,例如易于人编写和阅读,易于机器生成和解析。但是JSONXML数据传输的有效性要高出很多。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

GWTJSON

GWT中支持的客户端服务器端方法调用和数据传递的标准格式是RPC JSON并不是GWT支持的标准的数据传递格式。那么如何使用JSON来作为GWT的数据传递格式呢?需要以下几步。

第一,引用HTTPJSON支持。

第二,在客户端创建JSON数据,提交到服务器

第三,在服务器上重写数据格式解析的代码,使之支持JSON格式的数据

第四,在服务器上组织JSON格式的数据,返回给客户端。

第五,客户端解析服务器传回的JSON数据,正确的显示

引用HTTPJSON支持

找到.gwt.xml文件,在其中的

<inheritsname='com.google.gwt.user.User'/>

在之后添加如下的内容:

   <inherits name="com.google.gwt.json.JSON"/>
    <inherits name="com.google.gwt.http.HTTP"/>

其中com.google.gwt.json.JSON指的是要使用JSONcom.google.gwt.http.HTTP值得是通过HTTP调用服务器上的服务方法。

客户端构造JSON数据

客户端需要使用com.google.gwt.json.client包内的类来组装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类型值的超级类型

 

组合一个简单的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("nameis:" + name);
JSONArray jsonArray = jsonObject.getJSONArray("array");
for(int i = 0; i < jsonArray.length(); i++) {
    System.out.println("item " + i + " :" +jsonArray.getString(i));
}

其中payload指的是上述的JSON格式的数据。

那么如何写GWTService来得到Payload的数据呢?需要两点,第一,需要建立一个Service类,第二,覆盖父类的processCall方法。

示例代码:

packagecom.jpleasure.gwt.json.server;

importcom.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 implementsHelloWorldService {
    public String processCall(String payload) throwsSerializationException {
        try {
            JSONObjectjsonObject = new JSONObject(payload);
            String name= jsonObject.getString("name");

           System.out.println("name is:" + name);
            JSONArrayjsonArray = 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.action.testJson" extends="json-default" namespace="/" >  

9.           <action name="jsonUser" class="com.action.testJson.JsonAction" method="testUser">  

10.            <result type="json"/>  

11.        </action>  

12.        <!-- Add actions here -->  

13.    </package>   

14.</struts>  

<?xmlversion="1.0" encoding="UTF-8" ?>

<!DOCTYPE strutsPUBLIC

        "-//Apache SoftwareFoundation//DTD Struts Configuration 2.0//EN"

       "http://struts.apache.org/dtds/struts-2.0.dtd">

 

<struts>

 

    <packagename="com.action.testJson" extends="json-default" namespace="/">

        <action name="jsonUser"class="com.action.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

的说明

EditPage   BrowseSpace  AddPage  AddNews

Added by MusachyBarroso, last edited by ghostrolleron Jul 04, 2008  (viewchange)showcommenthidecomment

Comment: change "ignoreInterfaces" to"ignoreSMDMethodInterfaces" in interceptor parameters
View page history

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

rate-34268-90672

Rating?

·          1

·          2

·          3

·          4

·          5

Overview

The JSONplugin provides a "json" result type that serializes actions intoJSON. The serialization process is recursive, meaning that the whole objectgraph, starting on the action class (base class not included) will beserialized (root object can be customized using the "root" attribute).If the interceptor is used, the action will be populated from the JSON contentin the request, these are the rules of the interceptor:

1.    The "content-type"must be "application/json"

2.    The JSON content must be wellformed, seejson.org for grammar.

3.    Action must have a public"setter" method for fields that must be populated.

4.    Supported types for populationare: Primitives (int,long...String), Date, List, Map, Primitive Arrays, Otherclass (more on this later), and Array of Other class.

5.    Any object in JSON, that is tobe populated inside a list, or a map, will be of type Map (mapping fromproperties to values), any whole number will be of type Long, any decimalnumber will be of type Double, and any array of type List.

Giventhis JSON string:

{
   "doubleValue": 10.10,
   "nestedBean": {
      "name": "Mr Bean"
   },
   "list": ["A", 10, 20.20, {
      "firstName": "El Zorro"
   }],
   "array": [10, 20] 
}

Theaction must have a "setDoubleValue" method, taking either a"float" or a "double" argument (the interceptor willconvert the value to the right one). There must be a "setNestedBean"whose argument type can be any class, that has a "setName" methodtaking 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 asparameter either a "List", or any numeric array.

Installation

Thisplugin 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 usemaven, 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-maven-repo.googlecode.com/svn/trunk/</url>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
    <releases>
      <enabled>true</enabled>
    </releases>
</repository>

Customizing Serializationand Deserialization

Use theJSON annotation to customize the serialization/deserialization process.Available JSON annotation fields:

Name

Description

Default Value

Serialization

Deserialization

name

Customize field name

empty

yes

no

serialize

Include in serialization

true

yes

no

deserialize

Include in deserialization

true

no

yes

format

Format used to format/parse a Date field

"yyyy-MM-dd'T'HH:mm:ss"

yes

yes

Excluding properties

Acomma-delimited list of regular expressions can be passed to the JSON Resultand Interceptor, properties matching any of these regular expressions will beignored on the serialization 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

Acomma-delimited list of regular expressions can be passed to the JSON Result torestrict which properties will be serialized. ONLY properties matching any ofthese regular expressions will be included in the serialized output.

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.

<!-- Result fragment -->
<result type="json">
  <param name="includeProperties">
    ^entries\[\d+\]\.clientNumber,
    ^entries\[\d+\]\.scheduleNumber,
    ^entries\[\d+\]\.createUserId
  </param>
</result>

Root Object

Use the"root" attribute(OGNL expression) to specify the root object to beserialized.

<result type="json">
  <param name="root">
    person.job
  </param>
</result>

The"root" attribute(OGNL expression) can also be used on the interceptorto specify the object that must be populated,make sure this object is notnull.

<interceptor-ref name="json">
  <param name="root">bean1.bean2</param>
</interceptor-ref>

Wrap with Comments

wrapWithComments can turn safe JSON text into dangerous text. For example,

["*/ alert('XSS'); /*"]

Thanks to Douglas  Crockford for the tip!

If the"wrapWithComments" (false by default) attribute is set to true, thegenerated JSON is wrapped with comments like:

/* {
   "doubleVal": 10.10,
   "nestedBean": {
      "name": "Mr Bean"
   },
   "list": ["A", 10, 20.20, {
      "firstName": "El Zorro"
   }],
   "array": [10, 20] 
} */

This canbe used to avoid potentialJavascript Hijacks. To strip those commentsuse:

var responseObject = eval("("+data.substring(data.indexOf("\/\*")+2, data.lastIndexOf("\*\/"))+")");

Base Classes

Bydefault properties defined on base classes of the "root" object won'tbe 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

Bydefault, an Enum is serialized as a name=value pair where value = name().

publicenum AnEnum {
     ValueA,
     ValueB
  }
 
  JSON:  "myEnum":"ValueA"

Use the"enumAsBean" result parameter to serialize Enum's as a bean with aspecial property _name with value name(). All properties of the enum are alsoserialized.

publicenum AnEnum {
     ValueA("A"),
     ValueB("B");
 
     privateString val;
     
     public AnEnum(val) {
        this.val = val;
     }
     public getVal() {
        return val;
     }
   }
 
  JSON:  myEnum: { "_name": "ValueA", "val": "A" }

Enablethis parameter through struts.xml:

<result type="json">
  <param name="enumAsBean">true</param>
</result>

Compressing the output.

Set the enableGZIP attribute totrue to gzip the generated json response. The requestmust include"gzip" in the "Accept-Encoding" header for this to work.

<result type="json">
  <param name="enableGZIP">true</param>
</result>

Example

Setup Action

Thissimple action has some fields:

Example:

import java.util.HashMap;
import java.util.Map;
 
import com.opensymphony.xwork2.Action;
 
public class JSONExample {
    privateString field1 = "str";
    privateint[] ints = {10, 20};
    private Map map = new HashMap();
    privateString customName = "custom";
 
    //'transient' fields are not serialized
    privatetransientString field2;
 
    //fields without getter method are not serialized
    privateString field3;
 
    publicString execute() {
        map.put("John", "Galt");
        return Action.SUCCESS;
    }
 
    publicString getField1() {
        return field1;
    }
 
    public void setField1(String field1) {
        this.field1 = field1;
    }
 
    publicint[] 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")
    publicString getCustomName() {
        returnthis.customName;
    }
}

Write the mapping forthe action

1.    Add the map inside a packagethat 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 jsonplugin can be used to execute action methods from javascript and return theoutput. This feature was developed with Dojo in mind, so it usesSimple Method Definition to advertise the remoteservice. Let's work it out with an example(useless as most examples).

Firstwrite the action:

package smd;
 
import com.googlecode.jsonplugin.annotations.SMDMethod;
import com.opensymphony.xwork2.Action;
 
public class SMDAction {
    publicString smd() {
        return Action.SUCCESS;
    }
    
    @SMDMethod
    public Bean doSomething(Bean bean, int quantity) {
        bean.setPrice(quantity * 10);
        return bean;
    }
}

Methodsthat will be called remotelymust be annotated with the SMDMethod annotation,for security reasons. The method will take a bean object, modify its price andreturn it. The action can be annotated with theSMD annotation to customize the generatedSMD (more on that soon), and parameters can be annotated withSMDMethodParameter. Asyou can see, we have a "dummy", smdmethod. This method will be used to generate the Simple Method Definition (adefinition of all the services provided by this class), using the"json" result.

The beanclass:

package smd;
 
public class Bean {
    privateString type;
    privateint price;
    
    publicString getType() {
        return type;
    }
 
    public void setType(String type) {
        this.type = type;
    }
 
    publicint getPrice() {
        return price;
    }
 
    public void setPrice(int price) {
        this.price = price;
    }
 
}

Themapping:

<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>

Nothingspecial here, except thatboth the interceptor and the result must beapplied to the action, and "enableSMD" must be enabled for both.

Now thejavascript 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'sJsonService will make a request to the action to load the SMD, which willreturn a JSON object with the definition of the available remote methods, usingthat information Dojo creates a "proxy" for those methods. Because ofthe asynchronous nature of the request, when the method is executed, a deferredobject is returned, to which a callback function can be attached. The callbackfunction 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 problemswhile trying to serialize objects that are proxied. eg. when you have attachedAOP interceptors to your action.

In thissituation, the plugin will not detect the annotations on methods in youraction.

Toovercome this, set the "ignoreInterfaces" result parameter to false(true by default) to request that the plugin inspects all interfaces andsuperclasses 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 asthere 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("name", "yeeku");
      
return Action.SUCCESS;
     
}
    }

  在上面代码中,使用了JSON注释,注释时指定了name域,name域指定Action属性被序列化成JSON对象的属性名。除此之外,JSON注释还支持如下几个域:

  serialize:配置是否序列化该属性
  deserialize:配置是否反序列化该属性。
  format:配置用于格式化输出、解析日期表单域的格式。例如"yyyy-MM-dd'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>
 <constant name="struts.i18n.encoding"    value="UTF-8"/>
 <package name="example"    extends="json-default">
  <action name="JSONExample"    class="lee.JSONExample">
   <result type="json"/>
  </action>
 </package>
/struts>

  在上面配置文档中有两个值得注意的地方:

  第一个地方是配置struts.i18n.encoding常量时,不再是使用GBK编码,而是UTF-8编码,这是因为Ajax的POST请求都是以UTF-8的方式进行编码的。

  第二个地方是配置包时,自己的包继承了json-default包,而不再继承默认的default包,这是因为只有在该包下才有json类型的Result。

 

原创粉丝点击