SimpleXMLConverter 和改造 2.30。为啥序列化会因 ValueRequiredException 而崩溃?

Posted

技术标签:

【中文标题】SimpleXMLConverter 和改造 2.30。为啥序列化会因 ValueRequiredException 而崩溃?【英文标题】:SimpleXMLConverter and Retrofit 2.30. Why serialization crashes with ValueRequiredException?SimpleXMLConverter 和改造 2.30。为什么序列化会因 ValueRequiredException 而崩溃? 【发布时间】:2019-02-15 22:48:01 【问题描述】:

android 应用程序中,我正在使用管道 Retrofit + SimpleXmlConverter 发送 XMl 发布请求获取 XML 响应:

@Provides
@AuthorizationScope
Retrofit provideAuthorizationRetrofit(@Named("BASE_CRM_URL") String baseUrl,
                                      OkHttpClient client) 
    return new Retrofit.Builder().baseUrl(baseUrl)
            .addConverterFactory(SimpleXmlConverterFactory.createNonStrict())
            .client(client)
            .build();


@Provides
@AuthorizationScope
ApiAuthorizationService provideAuthorizationService(Retrofit retrofit) 
    return retrofit.create(ApiAuthorizationService.class);


public interface ApiAuthorizationService 

@POST("/")
Call<CardHolder> searchHolderByPhoneCard(@Body String messageSearchHolders2);

在 searchHolderByPhoneCard 调用中,我发送没有任何标题的原始字符串(我的 api 应用它)。请求和响应的实例:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Message Action="Search holders 2" Terminal_Type="77" Global_Type="ABC" Unit_ID="1" User_ID="1">
<Include>Holder_Card</Include>
<Item Mode="Clear" />
<Item Mode="Add">
    <Contacts>
        <Phone Value="+79600040318" IsNumber="True" />
    </Contacts>
</Item>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Holders Message_ID="0" IndexFrom="1" IndexTo="1" Count="1" Search_GUID="5BDE0E0A-2CD4-4B96-AD07-2D4BB5A15409">
<Holder>
    <Deleted>No</Deleted>
    <Group_ID>1</Group_ID>
    <Group_Name>
        <![CDATA[Владельцы карт "Перец"]]>
    </Group_Name>
    <Division_ID>1</Division_ID>
    <Division_Name>Головное подразделение</Division_Name>
    <Holder_ID>10000000040834</Holder_ID>
    <INN></INN>
    <External_Code></External_Code>
    <Unpay_Type_ID></Unpay_Type_ID>
    <Unpay_Type_Name></Unpay_Type_Name>
    <L_Name>Ермолин</L_Name>
    <F_Name>Павел</F_Name>
    <M_Name>Сергеевич</M_Name>
    <Full_Name>Ермолин Павел Сергеевич</Full_Name>
    <Birth>1992-12-14</Birth>
    <Gender>Male</Gender>
    <Marrital>Unknown</Marrital>
    <Smoke>No</Smoke>
    <Verification>Yes</Verification>
    <Image>No</Image>
    <Language_ID>1049</Language_ID>
    <Language_Name>
        <![CDATA[[RUS] Русский (Россия)]]>
    </Language_Name>
    <Source></Source>
    <Remarks></Remarks>
    <Holders_Cards>
        <Holder_Card>
            <Holder_ID>10000000040834</Holder_ID>
            <Card>
                <Card_Code>900221</Card_Code>
                <Is_Virtual_Card>Yes</Is_Virtual_Card>
                <Is_Confirm_Manager>No</Is_Confirm_Manager>
                <Status>Active</Status>
                <Carrier_Data></Carrier_Data>
                <Offered>2018-08-25</Offered>
                <Expired>2019-08-25</Expired>
                <Group_ID>5</Group_ID>
                <Group_Name>Virtual</Group_Name>
                <Holder_ID>10000000040834</Holder_ID>
                <Owner_ID></Owner_ID>
                <Verification>Yes</Verification>
            </Card>
        </Holder_Card>
    </Holders_Cards>
</Holder>

为了解析响应,我创建了非严格模型(我在大多数领域都没有需要)。型号代码:

@Root(name = "Holders", strict = false)
public class CardHolder 

@Attribute(name = "Count")
private int count;

@Element (name = "L_Name", required = false)
@Path("Holder")
private String secondName;

@Element (name = "F_Name", required = false)
@Path("Holder")
private String firstName;

@Element (name = "M_Name", required = false)
@Path("Holder")
private String thirdName;

@Element (name = "Birth", required = false)
@Path("Holder")
private String birth;

@Element (name = "Gender")
@Path("Holder")
private String gender;

@Element(name = "is_Virtual_Card", required = false)
@Path("Holder/Holders_Cards/Holder_Card/Card")
private String isVirtualCard;

public CardHolder() 




public int getCount() 
    return count;


public void setCount(final int count) 
    this.count = count;


public String getIsVirtualCard() 
    return isVirtualCard;


public void setIsVirtualCard(final String isVirtualCard) 
    this.isVirtualCard = isVirtualCard;


public String getSecondName() 
    return secondName;


public void setSecondName(final String secondName) 
    this.secondName = secondName;


public String getFirstName() 
    return firstName;


public void setFirstName(final String firstName) 
    this.firstName = firstName;


public String getThirdName() 
    return thirdName;


public void setThirdName(final String thirdName) 
    this.thirdName = thirdName;


public String getBirth() 
    return birth;


public void setBirth(final String birth) 
    this.birth = birth;


public String getGender() 
    return gender;


public void setGender(final String gender) 
    this.gender = gender;

结果,执行的 api 调用方法在 onFailure 回调异常中抛出这样的消息:

原因:org.simpleframework.xml.core.ValueRequiredException: Unable 满足@org.simpleframework.xml.Attribute(empty=, name=Count, required=true) 在字段“计数”私有 int 上

我已阅读有关此错误的文档,并且我了解这与无效的模型结构有关。但我不知道我哪里出错了,需要你的帮助来解决问题

【问题讨论】:

我猜count 没有得到值,因为默认情况下required=True 会导致错误。 【参考方案1】:

我找到了解决方案。问题是我试图将字符串原始请求作为@Body 发送。所有“text/plain”请求都应该这样包装:

String requestText = RequestBodyUtil.searchHolderByPhoneCard(phone);
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), requestText);

对于这种情况,阅读https://futurestud.io/tutorials/retrofit-2-how-to-send-plain-text-request-body 非常有用

【讨论】:

以上是关于SimpleXMLConverter 和改造 2.30。为啥序列化会因 ValueRequiredException 而崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

改造 2 和 Spring RestController

Android - Proguard 和改造 2?

java 领域和改造的Android模型类示例2。

Rxjava 2 - 使用领域和改造获取数据

更新改造到改造 2 后,OkHttpClient 损坏

如何访问数组改造 2 / android studio 中的对象“播放器”