我正在尝试从用PHP编写的soap-service(nuSOAP)接收一个复杂对象的数组。我正在尝试编写Android-Client并使用ksoap2库(3.0.0 RC.4)。 这个网上有一些“解决方案”和几个面临同样问题的人 - 无论如何,我尝试了许多不同的方式,现在我仍然困住了几天,所以我决定请你们帮忙。因此,我将向您展示我认为最接近我想要的代码。
首先要做的事情 - SOAP-Response(正文):
<SOAP-ENV:Body>
<ns1:GetListResponse xmlns:ns1="http://localhost/games_db/games_db.php">
<return xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="tns:DataPlusID[24]">
<item xsi:type="tns:DataPlusID">
<data xsi:type="xsd:string">shitload</data>
<ID xsi:type="xsd:int">4</ID>
</item>
<item xsi:type="tns:DataPlusID">
<data xsi:type="xsd:string">of</data>
<ID xsi:type="xsd:int">7</ID>
</item>
<item xsi:type="tns:DataPlusID">
<data xsi:type="xsd:string">imformation</data>
<ID xsi:type="xsd:int">10</ID>
</item>
</return>
</ns1:GetListResponse>
</SOAP-ENV:Body>
当我没有映射任何东西时“envelope.bodyIn.toString()”给了我以下内容。
GetListResponse{
return=[
DataPlusID{data=shitload; ID=4; },
DataPlusID{data=of; ID=7; },
DataPlusID{data=information; ID=10; }
];
}
以下是那些应该在某一天处理响应的课程......
public class GetListResponse implements KvmSerializable {
private Vector<DataPlusID> datavector = new Vector<DataPlusID>();
@Override
public Object getProperty(int arg0) {
return this.datavector;
}
@Override
public int getPropertyCount() {
return 1;
}
@Override
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) {
info.name = "return";
info.type = new Vector<DataPlusID>().getClass();
}
@Override
public void setProperty(int index, Object value) {
this.datavector = (Vector<DataPlusID>) value;
}
}
和
public class DataPlusID implements KvmSerializable
{
private String data;
private int ID;
@Override
public Object getProperty(int arg0) {
switch(arg0) {
case 0:
return data;
case 1:
return ID;
}
return null;
}
@Override
public int getPropertyCount() {
return 2;
}
@Override
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
switch(index) {
case 0:
info.type = PropertyInfo.STRING_CLASS;
info.name = "data";
break;
case 1:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "ID";
break;
default:break;
}
}
@Override
public void setProperty(int index, Object value) {
switch(index) {
case 0:
data = value.toString();
break;
case 1:
ID = Integer.parseInt(value.toString());
break;
default:
break;
}
}
}
以下是接收消息的代码
public GetListResponse GetList(String liste) throws Exception{
SoapObject request = new SoapObject(Namespace, MethodGetList);
request.addProperty("list", liste);
final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
envelope.addMapping(Namespace, "GetListResponse", new GetListResponse().getClass());
//envelope.addMapping(Namespace, "return", new Vector<DataPlusID>().getClass());
envelope.addMapping(Namespace, "item", new DataPlusID().getClass()); //tried also "DataPlusID" instead of "item"
try {
HttpTransportSE transport = new HttpTransportSE(URL);
transport.debug = true;
transport.call(ActionGetList, envelope);
Log.d("SOAPEnvelope", "Response: "+transport.responseDump);
} catch (Exception e){
Log.d("SOAPEnvelope", "Fehler bei Serverabfrage: "+e.toString());
}
//Log.d("SOAPEnvelope", "BodyIn: "+envelope.bodyIn.toString());
GetListResponse result = new GetListResponse();
result = (GetListResponse)envelope.bodyIn;
return result;
}
处理数据:
new Thread(new Runnable() {
public void run() {
try {
GetListResponse response = new GetListResponse();
response = GetList("genre");
//content of datavector is below
Vector<DataPlusID> datavector = new Vector<DataPlusID>();
datavector = (Vector<DataPlusID>) response.getProperty(0);
//EXCEPTION IS THROWN HERE
String x = (String) datavector.get(0).getProperty(0);
DataPlusID daten0 = new DataPlusID();
//WOULD ALSO HAPPEN HERE
daten0 = (DataPlusID) datavector.get(0);
String genre1 = (String) daten0.getProperty(0);
} catch (Exception e) {
Log.d("SOAPEnvelope", e.toString());
}
}
}).start();
以下是“datavector”的内容:
(java.util.Vector)
[DataPlusID{data=Action; ID=4; },
DataPlusID{data=Adventure; ID=7; },
DataPlusID{data=Aufbauspiel; ID=10; },
DataPlusID{data=Beat 'em up; ID=11; }]
抛出以下异常:
java.lang.ClassCastException: org.ksoap2.serialization.SoapObject cannot be cast to com.example.gamesdb_client.DataPlusID
最奇怪的是,虽然调试我实际上得到了我想要的价值。 - &GT;当我检查表达式“datavector.get(0).getProperty(0)”时,我得到:
(java.lang.String) shitload
所以他实际上是以正确的格式(字符串)看到数据,但当他试图将它附加到字符串变量时,他给了我一个ClassCastException?
无论如何,无论我尝试了什么,最终结果都是CCE,所以我很确定问题可以在映射(以及类定义)部分中找到:
1 envelope.addMapping(Namespace, "GetListResponse", new GetListResponse().getClass());
2 envelope.addMapping(Namespace, "item", new DataPlusID().getClass());
如果没有第1行,我会得到另一个CCE,所以我希望映射能够正常运行。 没有第2行没有任何变化,所以我很确定问题是在DataPlusID类中。
他无法将这些链接起来:
DataPlusID{data=shitload; ID=4; },
DataPlusID{data=of; ID=7; },
DataPlusID{data=information; ID=10; }
到DataPlusID-class。
所以希望有人可以看看这个,并让我知道如何解决问题。 也许只有一些基本的东西,我不明白。 - 让我的假期不浪费^^ 谢谢。
编辑:重新R4j
问题是,在示例代码中,他们使用了一个字符串向量(用this.add(value.toString())添加它。 这对我来说是不可能的,因为我有一个“DataPlusID”的向量。像this.add(value);不行,因为 他不能将参数(type:Object)放入DataPlusID-vector。
我试图通过将我的“GetListResponse”类的setProperty-method更改为:
来解决这个问题。public void setProperty(int index, Object value) {
this.datavector = (Vector<DataPlusID>) value;
for (int i = 0; i < datavector.size(); i++) {
this.add(datavector.elementAt(i));
}
}
这样我就可以将矢量的单个部分设置为类。
不幸的是,这只会在行中抛出相同的ClassCastExcepiton:
this.add(datavector.elementAt(i));
答案 0 :(得分:6)
原始postet问题的解决方案。
对R4j的信用 - 你的回答对我有很大帮助。
类定义 - GetListResponse:
public class GetListResponse implements KvmSerializable {
private Vector<SoapObject> datavector = new Vector<SoapObject>();
private DataArray dataarray = new DataArray();
@Override
public Object getProperty(int arg0) {
//return this.datavector.get(arg0);
return this.dataarray;
}
@Override
public int getPropertyCount() {
return 1;
}
@Override
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) {
info.name = "return";
info.type = new Vector<DataPlusID>().getClass();
}
@Override
public void setProperty(int index, Object value) {
this.datavector = (Vector<SoapObject>) value;
for(int i = 0; i < datavector.size(); i++) {
dataarray.setProperty(0, datavector.get(i));
}
}
}
DataArray中:
public class DataArray extends Vector<DataPlusID> implements KvmSerializable {
private static final long serialVersionUID = -1166006770093411055L;
@Override
public Object getProperty(int index) {
return this.get(index);
}
@Override
public int getPropertyCount() {
return this.size();
//return dataArray.length;
}
@Override
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) {
info.name = "item";
info.type = new DataPlusID().getClass();
}
@Override
public void setProperty(int index, Object value) {
SoapObject soapObject = new SoapObject();
soapObject = (SoapObject) value;
DataPlusID daten = new DataPlusID();
daten.setProperty(0, soapObject.getProperty("data"));
daten.setProperty(1, soapObject.getProperty("ID"));
this.add(daten);
}
}
DataPlusID:
public class DataPlusID implements KvmSerializable
{
private String data;
private int ID;
@Override
public Object getProperty(int arg0) {
switch(arg0)
{
case 0:
return data;
case 1:
return ID;
}
return null;
}
@Override
public int getPropertyCount() {
return 2;
}
@Override
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
switch(index)
{
case 0:
info.type = PropertyInfo.STRING_CLASS;
info.name = "data";
break;
case 1:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "ID";
break;
default:break;
}
}
@Override
public void setProperty(int index, Object value) {
switch(index)
{
case 0:
data = value.toString();
break;
case 1:
ID = Integer.parseInt(value.toString());
break;
default:
break;
}
}
}
接收数据的代码:
public GetListResponse GetList(String liste) throws Exception{
SoapObject request = new SoapObject(Namespace, MethodGetList);
request.addProperty("list", liste);
final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
//this is the only necessary mapping
envelope.addMapping(Namespace, "GetListResponse", new GetListResponse().getClass());
try {
HttpTransportSE transport = new HttpTransportSE(URL);
transport.debug = true;
transport.call(ActionGetList, envelope);
} catch (Exception e){
Log.d("SOAPEnvelope", "Fehler bei Serverabfrage: "+e.toString());
}
GetListResponse result = new GetListResponse();
result = (GetListResponse) envelope.bodyIn;
return result;
}
处理数据:
new Thread(new Runnable() {
public void run() {
try {
@SuppressWarnings("unchecked")
GetListResponse response = GetList("genre");
DataArray array = (DataArray) response.getProperty(0);
DataPlusID daten = (DataPlusID) array.getProperty(2);
String x = (String) daten.getProperty(0);
Log.d("SOAPEnvelope", "element 3 = "+x);
//Log says "element 3 = information"
} catch (Exception e) {
Log.d("SOAPEnvelope", e.toString());
}
}
}).start();
答案 1 :(得分:5)
据我所知,你的GetListResponse类应该扩展Vector而不是包含它。查看document here
public class GetListResponse extends Vector<DataPlusID>
implements KvmSerializable {
}
<强>更新强>:
对不起,我以前从未尝试过使用映射方法来处理复杂对象数组。您可以尝试another approach使用Vector<SoapObject>
构建循环迭代并手动获取其属性(您不需要GetListResponse
类)。像这样:
Vector<SoapObject> vectorOfSoapObject = (Vector<SoapObject>)envelop.getResponse();
for (SoapObject soapObject : vectorOfSoapObject) {
// put all properties into DataPlusID object
DataPlusID dataPlusIDObj = new DataPlusID();
dataPlusIDObj.setData(soapObject.getPropertyAsString("data"));
}
此方法位于the document,它应该有效。