移动开发 webservice接口传递复杂对象

作者:Young.Liu 分类: 技术 发布于:2013-9-12 18:09 ė2579次浏览 60条评论

在android的项目中,自从接触到webservice接口之后,我就试图通过使用ksoap2这个jar包来传递复杂对象,这里的复杂对象简单的来说指的就是自定义对象,其余的基本类型 (int和String)都是可以通过ksoap2包的基本方法传递的。之前一直有探索传递复杂对象的方法,理论上都是通过继承ksoap2包中的序列化类来实现的。其中找到比较好的,思路也是比较清楚的是eoe论坛上的一篇文章http://www.eoeandroid.com/thread-294714-1-1.html?_dsign=3bcebd0a在这篇文章中比较详细的讲解了作者的实现思路和具体的代码demo,我认为是比较好的。

遂在项目中利用这篇文章中的方法实现了一下,总体效果不错,但是作为一个接口实现来说还是麻烦,因为所有需要传递的类都要使用implements KvmSerializable方法实现ksoap2包里面的接口,每个类里面都要实现 getPropertyInfo等方法,使用起来实在麻烦。

在犹豫要不要把现有项目转到这个方法上的时候,我突然明白了一件事情:所谓的传递复杂对象也只是传递的字符串而已,本地实例化的对象并没有也不可能通过什么复杂高深的方法传递给webservice参与服务器的函数调用,在soap协议中,一切都只是字符串,准确的说都是xml格式的参数报文而已,而复杂的自定义对象的传递也只是传递了自定义类中的基本类型变量的名称和值而已,这些字符串发送到服务器端后,服务器使用和本地相同构造的类和传来的值进行相应的类的实例化而已,这个过程常被不怎么深入研究的童鞋理解成了本地把实例化的对象传到了服务端,作为跨平台的解决方案,没有什么类的实例可以通过某种方法在不同平台上互相传递,这点是需要明确的

想到这里,我突然想到了一个方法:能不能通过gson字符串的形式来传递自定义类呢?!!答案当然是可以的,原理和实现其实在谷歌的gson库中早就给我们定义好了,只是我们在脑海中固定了一种思维方式,理解错了复杂对象传递的过程。

以下我们写几个本地的json字符和class类之间的相互转换作为与webservice接口通信的前提热身,具体代码实现过程:


public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Button btn = (Button)findViewById(R.id.button1);
		btn.setOnClickListener(new OnClickListener() {//获取点击事件

			@Override
			public void onClick(View v) {
				GsonBuilder builder = new GsonBuilder();   //构造gson的builder
                                builder.excludeFieldsWithModifiers();  
				Gson gson = builder.create();   //创建gson对象

				MyClass myClass = new MyClass();  //初始化自定义的对象,这是我们要实现的“实例->gson”验证
				myClass.id = (333);  //赋值而已
				myClass.name=("qqq"); //复制而已
                                HashMap<Integer, Integer> myhashmap = new HashMap<Integer,Integer>() ;
				myhashmap.put(1, 1000);
				myClass.myhashmap=myhashmap;//验证自定义中有object类的情况
				YouClass youClass = new YouClass();//实例化另外一个class类,然后把这个类装进myClass类中的最后一个参数,目的是为了让myClass实例更加复杂一些
				youClass.id=11;
				youClass.name="you";
				myClass.youClass=youClass;
				String stuStr = gson.toJson(myClass);  //利用gson包,把已经实例化的类变成字符串并打印,输出为
                                System.out.println(stuStr);            //{"youClass":{"name":"you","id":11},"myhashmap":{"1":1000},"name":"qqq","id":333}
				MyClass muClass = gson.fromJson(stuStr, MyClass.class);//从刚才答应的字符中实例化另外一个Class实例 muClass,并判断该对象是否创建成功,输出为 {1=1000.0}
				System.out.println(muClass.myhashmap);

			}
		});
	}
	//两个自定义类
	class MyClass
	{
		public int id;
		public String name;
		public Object myhashmap;
		public YouClass youClass;
	} 
	
	class YouClass
	{
		public int id;
		public String name;
	}
}

好,经过以上的验证,我们大致上是实现了本地客户端的实例化对象到json字符串的转换和从json实例化某个类。下面的难点是服务器端如何把传上来的json字符串实例化对象呢? 这里的服务端使用.net做为服务接口,在c#中微软已经实现了和gson库类似的功能,可以完成实例化对象到json的转换,也可以通过json实例化某个类,当然,前提是json是从相同构造类中转换而来的,一下c#的代码可以帮助你加深一下理解:




/// <summary>

/// JSON序列化

/// </summary>
public static string JsonSerializer<T>(T t)
{
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));

    MemoryStream ms = new MemoryStream();

    ser.WriteObject(ms, t);

    string jsonString = Encoding.UTF8.GetString(ms.ToArray());

    ms.Close();

  return jsonString;
 
}

 <summary>

  /// JSON反序列化

 /// </summary>

 public static T JsonDeserialize<T>(string jsonString)

 {

     DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));

     MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
     T obj = (T)ser.ReadObject(ms);
     return obj;
}
class MyClass
{
	public int id;
	public String name;
	public Object myhashmap;
	public YouClass youClass;
} 
	
class YouClass
{
	public int id;
	public String name;
}

MyClass myClass = new MyClass();  //初始化自定义的对象,这是我们要实现的“实例->gson”验证
myClass.id = (333);  //赋值而已
myClass.name=("qqq"); //复制而已
HashMap<Integer, Integer> myhashmap = new HashMap<Integer,Integer>() ;
myhashmap.put(1, 1000);
myClass.myhashmap=myhashmap;//验证自定义中有object类的情况
YouClass youClass = new YouClass();//实例化另外一个class类,然后把这个类装进myClass类中的最后一个参数,目的是为了让myClass实例更加复杂一些
youClass.id=11;
youClass.name="you";
myClass.youClass=youClass;

string jsonString = JsonHelper.JsonSerializer<MyClass>(myClass);//获得json字符串,可以通过String的形式返回给客户端

string jsonString = "
{\"youClass\":{\"name\":\"you\",\"id\":11},\"myhashmap\":{\"1\":1000},\"name\":\"qqq\",\"id\":333}";
Myclass myClass = JsonHelper.JsonDeserialize<MyClass>(jsonString);





其实稍微懂C#的人看到以上代码就应该理解了,同样使用刚才在本地定义的两个类,利用相同的参数,在C#中实现了相同的功能,而在实际项目中,本地把实例化后的类使用gson库序列化为json字符串,并把这个json以普通String的形式上传到服务器,服务端获得String后,使用反序列化用json字符串实例化一个新的类,只要这个类在客户端和服务器定义为相同的构造就可以了。


相比使用ksoap2包支持的序列化的实现方式,这种使用gson包实现的更为简单便捷,许多难点细节都被谷歌在gson中实现并透明化了,我们只需要调用几行代码就可以把实例转化json了,相比要自己继承KvmSerializable自定义类来说要简单太多了。

本文出自 我的技术积累,转载时请注明出处及相应链接。


Ɣ回顶部