Android ksoap2 nullable type

不想你离开。 提交于 2019-12-11 04:00:57

问题


I am trying to connect to a WCF .Net Web Service from an Android device using the Ksoap2 library. Everything works fine, I've been able to send and receive complex objects so far (after a LOT of troubleshooting). However, I'm now running into the problem of nullable types. On the server-side, a lot of the attributes I'll be sending will be nullable. When I try to send these as null from the Android side I get a deserialization error because ksoap puts null=true instead of nil=true. Here is some working SOAP XML from a test driver as well as the current XML from the Android client.

Working Test Driver XML

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
    <AddNullables xmlns="http://TJIsGhey/Tester">
        <NumbersToAdd xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <Input1>7</Input1>
            <Input2 i:nil="true" />
        </NumbersToAdd>
    </AddNullables>
</s:Body>
</s:Envelope>

Android Client XML

<v:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
    <v:Header />
    <v:Body>
        <AddNullables xmlns="http://TJIsGhey/Tester" id="o0" c:root="1">
            <NumbersToAdd i:type="n0:NullablesIn" xmlns:n0="http://TJIsGhey/Tester">
                <Input1 i:type="d:int">6</Input1>
                <Input2 i:null="true" />
            </NumbersToAdd>
        </AddNullables>
    </v:Body>
</v:Envelope>

And here is the error message I'm receiving:

There was an error deserializing the object of type Tester.NullablesIn. The value '' cannot be parsed as the type 'Int32'.

Any help would be greatly appreciated!


回答1:


I had the same issue. After I drilled inside Ksoap2 source code I found the issue. You have 2 possible solutions the first and easy one would be to use VER12 at the SoapSerializationEnvelope. Since Ksoap2 is only using nil attribute since VER12 and up. However you might be effected by this change so you have another option: Inherit the SoapSerializationEnvelope and override the writeProperty method of this class. as so:

public class ExtendedSoapSerializationEnvelope extends
    SoapSerializationEnvelope {

public ExtendedSoapSerializationEnvelope(int version) {
    super(version);
}

@Override
protected void writeProperty(XmlSerializer writer, Object obj,
        PropertyInfo type) throws IOException {
    if (obj == null) {

        if (!(obj instanceof SoapObject)) {
            // assuming object implements KvmSerializable or other type of
            // Serialization interface
            writer.attribute(xsi, version >= VER11 ? "nil" : "null", "true");

        } else {
            // assuming SoapObject being used with VER12 and up
            writer.attribute(xsi, version >= VER12 ? "nil" : "null", "true");
        }
        return;
    }
    super.writeProperty(writer, obj, type);
}}

If you know that your webService always work with nil you could skip this check altogther and just use:

    @Override
protected void writeProperty(XmlSerializer writer, Object obj,
        PropertyInfo type) throws IOException {
    if (obj == null) {
        writer.attribute(xsi, "nil", "true");
        return;
    }

    super.writeProperty(writer, obj, type);

}



回答2:


Workaround method is ignore this "<element type>" using parameter skipNullProperties like this:

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.skipNullProperties=true;



回答3:


problem was solved

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpsTransportSE;
import java.net.URISyntaxException;

public class MainActivity extends AppCompatActivity {
    private static final String URL = "https://services.rs.ge/WayBillService/WayBillService.asmx?WSDL";

    TextView tv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        tv = new TextView(this);
        String[] params = new String[]{"save_waybill","s22:12345678910","123456"};
        new MyAsyncTasc().execute(params);
        setContentView(tv);
    }

    class MyAsyncTasc extends AsyncTask<String,Void,String> {
        @Override
        protected String doInBackground(String... params) {
            String SOAP_ACTION="http://tempuri.org/"+params[0];
            int timeOut = 60000;
            SoapSerializationEnvelope __envelope=new SoapSerializationEnvelope(SoapEnvelope.VER11);
            SoapObject request = new SoapObject("http://tempuri.org/", params[0]);
            __envelope.dotNet = true;
            __envelope.setOutputSoapObject(request);
            request.addProperty("su", params[1]);
            request.addProperty("sp", params[2]);

            //------------------ SoapObject
            SoapObject waybill1 = new SoapObject("", "WAYBILL");
            SoapObject goods1 = new SoapObject("", "GOODS");
            SoapObject good_list1 = new SoapObject("", "GOODS_LIST");
            waybill1.addProperty("SELER_UN_ID", 1149251);
            waybill1.addProperty("ID", 0);
            waybill1.addProperty("TYPE", 1);
            waybill1.addProperty("STATUS", 1);
            waybill1.addProperty("START_ADDRESS", "START_ADDRESS");
            waybill1.addProperty("END_ADDRESS", "END_ADDRESS");
            waybill1.addProperty("DRIVER_TIN", "61007004242");
            waybill1.addProperty("CAR_NUMBER", "AAA000");
            waybill1.addProperty("CHEK_DRIVER_TIN", 1);
            waybill1.addProperty("TRANSPORT_COAST", 0);
            waybill1.addProperty("TRAN_COST_PAYER", 2);
            waybill1.addProperty("TRANS_ID", 1);

            goods1.addProperty("ID", 0);
            goods1.addProperty("W_NAME", "W_NAME");
            goods1.addProperty("UNIT_ID", 1);
            goods1.addProperty("QUANTITY", 2);
            goods1.addProperty("PRICE", 1);
            goods1.addProperty("AMOUNT", 2);
            goods1.addProperty("BAR_CODE", "1");

            good_list1.addProperty("GOODS", goods1);

            goods1 = new SoapObject("", "GOODS");
            goods1.addProperty("ID", 0);
            goods1.addProperty("W_NAME", "W_NAME2");
            goods1.addProperty("UNIT_ID", 1);
            goods1.addProperty("QUANTITY", 4);
            goods1.addProperty("PRICE", 1);
            goods1.addProperty("AMOUNT",4);
            goods1.addProperty("BAR_CODE", "2");

            good_list1.addProperty("GOODS", goods1);

            waybill1.addProperty("GOODS_LIST", good_list1);
            SoapObject wib_send = new SoapObject("", "waybill");
            wib_send.addProperty("WAYBILL", waybill1);
            request.addProperty("waybill", wib_send);

            java.net.URI uri = null;
            try {
                uri = new java.net.URI(URL);
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
            int port=uri.getPort()>0?uri.getPort():443;
            HttpsTransportSE httpTransport= new HttpsTransportSE(uri.getHost(), port, uri.getPath(), timeOut);
            httpTransport.debug = true;
            try {
                httpTransport.call(SOAP_ACTION, __envelope);
                SoapObject resultRequestSOAP = (SoapObject) __envelope.bodyIn;
                return resultRequestSOAP.toString();
            } catch(Exception exp){
                return "Error";
            }
        }
        @Override
        protected void onPostExecute(final String result) {
            tv.setText(result);
        }
    }
}


来源:https://stackoverflow.com/questions/10014164/android-ksoap2-nullable-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!