kSoap2 POJO映射类强制转换异常

时间:2014-11-18 10:44:33

标签: java android soap android-ksoap2

我很难在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;
        }

    }
}

1 个答案:

答案 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。

希望它会有所帮助。 马尔钦