使用Struts 2將客戶端JSON資料對映為伺服器端Java物件
上文()介紹瞭如何將Java物件序列化成JSON格式並傳到客戶端。這篇文章就說說如何將客戶端的JSON資料對映為伺服器端的Java物件。
pom.xml
需要引入struts2-json-plugin包。
<dependencies> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.3.12</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-json-plugin</artifactId> <version>2.3.12</version> </dependency> </dependencies>
struts.xml
package extends要增加”json-default”;負責接收資料的SaveAction必須設定interceptor-ref為json。否則將無法得到客戶端傳來的資料。
<package name="sandbox" namespace="/" extends=" struts-default, json-default"> <action name="main" class="sandbox.z.MainAction"> <result>/jsp/main.jsp</result> </action> <action name="test" class="sandbox.z.TestAction"> <result type="json" /> </action> <action name="save" class="sandbox.z.SaveAction"> <interceptor-ref name="json"> <param name="contentType">application/json</param> </interceptor-ref> <result type="json" /> </action> </package>
main.jsp
<script> require([ "dojo/ready", "dojo/_base/xhr", "dojo/json", "dijit/registry" ], function(ready, xhr, JSON, registry) { ready(function() { var data = { name: "john", age: 30, height: 1.78, scores: [85, 90], score_array: [85, 90], array: [85,"Struts2"], books_map: { "struts2": 85 }, book: { "name": "Struts2", "price": 85.3, "sellers":[ "SA", "SB" ] } }; var xhrArgs = { url : "/save.action", handleAs : "json", contentType : 'application/json; charset=utf-8', postData: dojo.toJson(data), /*data必須放在postData中,並轉成json格式*/ sync : true }; var deferred = xhr.post(xhrArgs); /*伺服器收到json資料,並轉成相應的JAVA物件,最後依舊返回給客戶端*/ deferred.then(function(result) { var output = JSON.stringify(result); console.log(output); }); }); }); </script>
SaveAction.java
SaveAction中,和客戶端data中對應的屬性會得到相應的資料。
package sandbox.z;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.opensymphony.xwork2.ActionSupport;
public class SaveAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private double height;
private int[] scores;
private List<Integer> score_array = new ArrayList<Integer>();
public void setScore_array(List<Integer> score_array) {
this.score_array = score_array;
}
public List<Integer> getScore_array() {
return score_array;
}
private List array = new ArrayList();
public List getArray() {
return array;
}
public void setArray(List array) {
this.array = array;
}
private Map books_map = new HashMap();
public void setBooks_map(Map books_map) {
this.books_map = books_map;
}
public Map getBooks_map() {
return books_map;
}
private Book book = new Book();
public void setBook(Book book) {
this.book = book;
}
public Book getBook() {
return book;
}
public String execute() {
return SUCCESS;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setHeight(double height) {
this.height = height;
}
public double getHeight() {
return height;
}
public void setscores(int[] scores) {
this.scores = scores;
}
public int[] getscores() {
return scores;
}
}
Firebug console
可以用FirebugConsole檢驗伺服器端是否正確接收到資料了。
{"age":30,"array":[85,"Struts2"],"book":{"name":"Struts2","price":85.3,"sellers":["SA","SB"]},"books_map":{"struts2":85},"height":1.78,"name":"john","score_array":[85,90],"scores":[85,90]}
總結
正常情況下,從JSON到JAVA的轉換也比較簡單。關鍵是屬性的名字和相應的資料型別符合轉換的要求。
那當屬性名字或資料型別不符合的時候,會產生什麼樣的問題呢?
1. 屬性的資料型別不對
當JSON給相應的屬性賦值時,若沒有嚴格按照定義的資料型別賦值,則對於某些不匹配Struts2會進行自動轉換。比如給String型別的賦了數值型的值,則該數值到伺服器端後,會被轉換成String型別。但如果對String型別的賦列表型的值,則會報錯。
這兒還有一種取巧的辦法,比如將JAVA的某個屬性型別設成Object,則無論JSON中給這個屬性賦什麼值,伺服器端都不會報錯。不過這樣一來,哪怕伺服器端拿到這個屬性值了,也很難將其對映到某個具體的資料型別上,並進行進一步的操作。因此最好還是定義比較嚴格的資料型別,並要求客戶端JSON賦值時遵守資料型別的約定。
2. 屬性少了
屬性少了不會報錯,而是相應的JAVA物件的屬性值為null。
3. 屬性多了
若在JSON中多了Action中未定義的屬性,Action會直接忽視而不報錯。