PHP (nuSOAP) で記述された SOAP サービスから複雑なオブジェクトの配列を取得しようとしています。Android-Client を作成し、ksoap2 ライブラリ (3.0.0 RC.4) を使用しようとしています。このオンラインにはいくつかの「解決策」があり、同じ問題に直面していた何人かの人々がいます. そこで、私の意見では、私が得たいものに最も近いコードを紹介します。
まず最初に - SOAP 応答 (ボディ):
<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
最も奇妙なことは、デバッグ中に、取得したい値を実際に正確に取得することです。--> 式 "datavector.get(0).getProperty(0)" を調べると、次のようになります。
(java.lang.String) shitload
つまり、彼は実際にはデータを正しい形式 (文字列) で見ていますが、それを文字列変数にアタッチしようとすると、ClassCastException が発生しますか?
とにかく、私が何を試しても、最終結果は常にCCEだったので、問題はマッピング(およびクラス定義のofc)部分で見つかると確信しています:
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 クラスに。
うまくいけば、誰かがこれを見て、問題を解決する方法を教えてくれることを願っています. たぶん、私が理解していない基本的なことがいくつかあります。- 私の休暇を無駄にしないように^^ ありがとうございます。
編集:再R4j
問題は、サンプル コードでは、文字列のベクトルを使用している (this.add(value.toString()) で追加する) ことです。「DataPlusID」のベクトルがあるため、これは私には不可能です。 like this.add(value); は、引数 (タイプ: オブジェクト) を DataPlusID-vector に入れることができないため、機能しません。
「GetListResponse」クラスの setProperty メソッドを次のように変更して、これを解決しようとしました。
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));