我很难在Android上使用kSOAP2库。我能够发送请求并获得响应,但我想将响应的内容映射到普通的java对象。基本上,kSOAP2允许您通过将映射的参数指定到addMapping()方法来实现。无论如何,当我尝试将响应转换为我的Java对象时,我遇到了类强制转换异常。这是我的实施:
final SoapSerializationEnvelope envelope = LoginInfo.buildLoginObject(login,password);
envelope.addMapping(NAMESPACE, "GetCustomerByIdPwdResponse", new GetCustomerByIdPwdResponse().getClass());
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
HttpTransportSE httpTransport = new HttpTransportSE("URL");
httpTransport.debug = true;
try {
httpTransport.call(URL, envelope);
Log.d("SOAP OBJECT SENT",httpTransport.requestDump);
Log.d("SOAP OBJECT RESPONSE",httpTransport.responseDump);
GetCustomerByIdPwdResponse customerByIdPwd = (GetCustomerByIdPwdResponse)envelope.bodyIn;
} catch (IOException | XmlPullParserException e) {
e.printStackTrace();
}
return null;
}
}.execute();
这是我得到的请求和回复,它们都很好:
请求:
<?xml version="1.0" encoding="UTF-8"?>
<v:Envelope xmlns:v="http://www.w3.org/2003/05/soap-envelope" xmlns:c="http://www.w3.org/2003/05/soap-encoding" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<v:Header>
<n0:To xmlns:n0="http://www.w3.org/2005/08/addressing">To</n0:To>
<n1:Action xmlns:n1="http://www.w3.org/2005/08/addressing">rexwebservices/IWebShopServices/GetCustomerByIdPwd</n1:Action>
</v:Header>
<v:Body>
<GetCustomerByIdPwd xmlns="rexwebservices" xmlns:ns2="http://schemas.datacontract.org/2004/07/RexWebServices" xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/" id="o0" c:root="1">
<loginMail i:type="d:string">...</loginMail>
<pwdSHA1 i:type="d:string">...</pwdSHA1>
</GetCustomerByIdPwd>
</v:Body>
回应:
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">rexwebservices/IWebShopServices/GetCustomerByIdPwdResponse</a:Action>
</s:Header>
<s:Body>
<GetCustomerByIdPwdResponse xmlns="rexwebservices">
<GetCustomerByIdPwdResult xmlns:b="http://schemas.datacontract.org/2004/07/RexWebServices" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<b:Customer>
<b:FirstName>...</b:FirstName>
<b:Id>...</b:Id>
<b:IsActived>true</b:IsActived>
<b:IsLockedOut>false</b:IsLockedOut>
<b:IsNewsLetterAccepted>false</b:IsNewsLetterAccepted>
<b:LandLinePhone />
<b:LastName>...</b:LastName>
<b:LoginMail>...</b:LoginMail>
<b:MobilePhone />
<b:Title>Mr</b:Title>
</b:Customer>
<b:ErrorMessage>+00X00000</b:ErrorMessage>
<b:SessionId>SID</b:SessionId>
</GetCustomerByIdPwdResult>
</GetCustomerByIdPwdResponse>
</s:Body>
</s:Envelope>
这是我在尝试创建POJO时遇到的错误:
11-18 11:36:57.967: E/AndroidRuntime(19208): Caused by: java.lang.ClassCastException: org.ksoap2.serialization.SoapObject cannot be cast to com.example.ksoaptest.GetCustomerByIdPwdResponse
11-18 11:36:57.967: E/AndroidRuntime(19208): at com.example.ksoaptest.MainActivity$2.doInBackground(MainActivity.java:70)
11-18 11:36:57.967: E/AndroidRuntime(19208): at com.example.ksoaptest.MainActivity$2.doInBackground(MainActivity.java:1)
11-18 11:36:57.967: E/AndroidRuntime(19208): at android.os.AsyncTask$2.call(AsyncTask.java:288)
11-18 11:36:57.967: E/AndroidRuntime(19208): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
11-18 11:36:57.967: E/AndroidRuntime(19208): ... 4 more
任何帮助都会很棒,因为这是让我开始实施网络服务的最后一步。
谢谢!
更新:
这是我的客户的课程。我在尝试将客户映射到我的RexUser类时遇到错误。
我将envelope.addMapping("rexwebservices","RexUser",RexUser.class);
映射添加到了我的信封中。
在将客户数据保存到用户对象时,我遇到Caused by: java.lang.RuntimeException: Unknown Property: FirstName
错误。
public class RexUser implements KvmSerializable{
public static final int FIRSTNAME = 0;
public static final int ID = 1;
public static final int LASTNAME = 6;
public static final int LOGINMAIL = 7;
public static final int MOBILEPHONE = 8;
public static final int LANDLINEPHONE = 5;
public static final int TITLE = 9;
public static final int IS_ACTIVATED = 2;
public static final int IS_LOCKED_OUT = 3;
public static final int IS_NEWSLETTER_ACCEPTED = 4;
String FirstName;
long Id;
boolean IsActived;
boolean IsLockedOut;
boolean IsNewsLetterAccepted;
String LandLinePhone;
String LastName;
String LoginMail;
String MobilePhone;
String Title;
public RexUser(String firstName, long id, boolean isActivated,
boolean isLockedOut, boolean isNewsLetterAccepted,
String landLinePhone, String lastName, String loginMail,
String mobilePhone, String title) {
super();
this.FirstName = firstName;
this.Id = id;
this.IsActived = isActivated;
this.IsLockedOut = isLockedOut;
this.IsNewsLetterAccepted = isNewsLetterAccepted;
this.LandLinePhone = landLinePhone;
this.LastName = lastName;
this.LoginMail = loginMail;
this.MobilePhone = mobilePhone;
this.Title = title;
}
public RexUser() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
HashMap<String,Object> desc = new HashMap<String,Object>();
desc.put("First name",FirstName);
desc.put("ID",Id);
desc.put("is Actived", IsActived);
desc.put("is Locked Out",IsLockedOut);
desc.put("isNewsLetterAccepted", IsNewsLetterAccepted);
desc.put("Land Line Phone", LandLinePhone);
desc.put("lastname", LastName);
desc.put("login Mail", LoginMail);
desc.put("mobile phone",MobilePhone);
desc.put("title", Title);
return desc.toString();
}
@Override
public Object getProperty(int arg0) {
switch(arg0){
case 0:
return FirstName;
case 1:
return Id;
case 2:
return IsActived;
case 3:
return IsLockedOut;
case 4:
return IsNewsLetterAccepted;
case 5:
return LandLinePhone;
case 6:
return LastName;
case 7:
return LoginMail;
case 8:
return MobilePhone;
case 9:
return Title;
default:
return null;
}
}
@Override
public int getPropertyCount() {
return 10;
}
@Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) {
switch(arg0){
case 0:
arg2.name = "First Name";
arg2.type = String.class;
break;
case 1:
arg2.name = "ID";
arg2.type = int.class;
break;
case 2:
arg2.name = "Is Actived";
arg2.type = boolean.class;
break;
case 3:
arg2.name = "Is Locked Out";
arg2.type = boolean.class;
break;
case 4:
arg2.name = "Is Newsletter Accepted";
arg2.type = boolean.class;
break;
case 5:
arg2.name = "Landline Phone";
arg2.type = String.class; break;
case 6:
arg2.name = "Last Name";
arg2.type = String.class;
break;
case 7:
arg2.name = "Login mail";
arg2.type = String.class;
break;
case 8:
arg2.name = "Mobile Phone";
arg2.type = String.class;
break;
case 9:
arg2.name = "Title";
arg2.type = String.class;
break;
default:
break;
}
}
@Override
public void setProperty(int arg0, Object arg1) {
switch(arg0){
case 0:
FirstName = (String)arg1;
break;
case 1:
Id = (int)arg1;
break;
case 2:
IsActived = (boolean)arg1;
break;
case 3:
IsLockedOut = (boolean)arg1;
break;
case 4:
IsNewsLetterAccepted = (boolean)arg1;
break;
case 5:
LandLinePhone = (String)arg1;
break;
case 6:
LastName = (String)arg1;
break;
case 7:
LoginMail = (String)arg1;
break;
case 8:
MobilePhone = (String)arg1;
break;
case 9:
Title = (String)arg1;
break;
default:
break;
}
}
}
答案 0 :(得分:1)
首先确保您的结构中的大多数外部对象的命名空间(GetCustomerByIdPwdResponse)是“rexwebservices”,因此添加映射将是......那样:
envelope.addMapping("rexwebservices", "GetCustomerByIdPwdResponse", GetCustomerByIdPwdResponse.class);
envelope.addMapping("rexwebservices", "GetCustomerByIdPwdResult", GetCustomerByIdPwdResult.class);
第二件事 - 您定义的类只是您的响应的外框。我试图定义可序列化的响应和你的结构的第一级。您包含的响应已正确解析为它们。
public class GetCustomerByIdPwdResponse implements KvmSerializable {
GetCustomerByIdPwdResult getCustomerByIdPwdResult;
@Override
public Object getProperty(int arg0) {
if(arg0==0){
return getCustomerByIdPwdResult;
}
return null;
}
@Override
public int getPropertyCount() {
return 1;
}
@Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) {
if(arg0==0){
arg2.name="GetCustomerByIdPwdResult";
arg2.type=GetCustomerByIdPwdResult.class;
}
}
@Override
public void setProperty(int arg0, Object arg1) {
if(arg0==0){
getCustomerByIdPwdResult=(GetCustomerByIdPwdResult)arg1;
}
}
}
public class GetCustomerByIdPwdResult implements KvmSerializable {
SoapObject Customer; //here goes Customer class ofcourse
String ErrorMessage;
String SessionId;
@Override
public Object getProperty(int arg0) {
switch(arg0){
case 0: return Customer;
case 1: return ErrorMessage;
case 2: return SessionId;
}
return null;
}
@Override
public int getPropertyCount() {
return 3;
}
@Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) {
switch(arg0){
case 0: arg2.name="Customer"; arg2.type=SoapObject.class;break; //Customer class
case 1: arg2.name="ErrorMessage"; arg2.type=PropertyInfo.STRING_CLASS;break;
case 2: arg2.name="SessionId"; arg2.type=PropertyInfo.STRING_CLASS;break;
}
}
@Override
public void setProperty(int arg0, Object arg1) {
switch(arg0){
case 0: Customer=(SoapObject)arg1;break;//Customer class
case 1: ErrorMessage=(String)arg1;break;
case 2: SessionId=(String)arg1;break;
}
}
}
我离开了Customer类 - 这就是为什么GetCustomerByIdPwdResult类中的Customer字段被声明为SoapObject。
希望它会有所帮助。 马尔钦