java - ksoap2 SOAP를 통해 복잡한 객체 배열 수신

기사 출처 java android ksoap2

PHP (nuSOAP)로 작성된 SOAP 서비스에서 복잡한 객체 배열을 수신하려고합니다. 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


가장 이상한 점은 디버깅하는 동안 내가 원하는 값을 실제로 얻는다는 것입니다.
-> "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 클래스에.

누군가가 이것을보고 문제를 해결하는 방법을 알려줄 수 있기를 바랍니다.
내가 이해하지 못한 기본적인 것들이있을 수도 있습니다. -휴가를 낭비하지 않게 해주세요 ^^
감사합니다.

편집 : Re- R4j

문제는 샘플 코드에서 문자열 벡터를 사용하고 있다는 것입니다 (this.add (value.toString ()으로 추가).
"DataPlusID"벡터가 있기 때문에 이것은 나에게 가능하지 않습니다. 이것과 같은 것 .add (value); 작동하지 않습니다.
그는 인수 (유형 : 개체)를 DataPlusID- 벡터에 넣을 수 없습니다.

"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));
내가 아는 한, GetListResponse 클래스는 Vector를 포함하는 대신 확장해야합니다. document here 확인

 public class GetListResponse extends Vector<DataPlusID> 
                                implements KvmSerializable {
  }


최신 정보:
죄송합니다. 전에 복잡한 객체 배열에 매핑 방식을 사용해 본 적이 없습니다. Vector<SoapObject>를 사용하여 반복되는 루프를 구축하는 another approach를 시도하고 속성을 직접 가져올 수 있습니다 (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에 있으며 작동해야합니다.

이 질문에 대해 Stack Overflow에서 비슷한 토론을 찾았습니다: https://stackoverflow.com/questions/14186279/

관련 기사
java - Hibernate 4.1.9 (최신 최종 빌드)가 '중첩 된 트랜잭션이 지원되지 않음'보고
java - Spring RestTemplate으로 배열을 보내는 방법은 무엇입니까?
java - superClass의 private 멤버가 subClass… Java에 상속됩니까?
java - setter 메서드에 직접 문자열 배열 값 전달
java - Java는 long을 4 바이트로 변환
java - 분할 날짜 문자열에 대해 제안되는 방법은 무엇입니까?
java - 스윙 라벨에 애니메이션 GIF 추가
java - 자바에서 파일 작업
java - Java의 Null 참조
java - 유형이 정의되지 않은 Java 매개 변수