在Android上使用XStream时如何注释订单字段?

时间:2013-06-07 07:34:59

标签: android xml xsd schema xstream

我需要从Android上的java对象生成XML。 XML节点必须在 确定的顺序。这是我得到的(这些字段按字母顺序排列):

<soap:Envelope xmlns:cwmp="urn:dslforum-org:cwmp-1-0" 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soap:Body>
    <cwmp:Inform>
      <CurrentTime>2013-06-07 07:11:20.561 UTC</CurrentTime>
      <DeviceId>
        <OUI>002615</OUI>
        <Manufacturer>Conexant</Manufacturer>
        <ProductClass>ADSL2+ IAD</ProductClass>
        <SerialNumber>00261559a496</SerialNumber>
      </DeviceId>
      <Event soapenc:arrayType="cwmp:EventStruct[1]">
        <EventStruct>
          <CommandKey></CommandKey>
          <EventCode>0 BOOTSTRAP</EventCode>
        </EventStruct>
      </Event>
      <ParameterList soapenc:arrayType="cwmp:ParameterValueStruct[1]">
        <ParameterValueStruct>
          <name>InternetGatewayDevice.DeviceInfo.SpecVersion</name>
          <value>1.0</value>
        </ParameterValueStruct>
      </ParameterList>
      <MaxEnvelopes>1</MaxEnvelopes>
      <RetryCount>0</RetryCount>
    </cwmp:Inform>
  </soap:Body>
  <soap:Header>
    <ID soap:mustUnderstand="1">
      <string>00001</string>
    </ID>
  </soap:Header>
</soap:Envelope>

这就是我想要的:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soap:Header>
    <ID soap:mustUnderstand="1">
      <string>00001</string>
    </ID>
  </soap:Header>
  <soap:Body>
    <cwmp:Inform>
      <DeviceId>
        <Manufacturer>Conexant</Manufacturer>
        <OUI>002615</OUI>
        <ProductClass>ADSL2+ IAD</ProductClass>
        <SerialNumber>00261559a496</SerialNumber>
      </DeviceId>
      <Event soapenc:arrayType="cwmp:EventStruct[1]">
        <EventStruct>
          <EventCode>0 BOOTSTRAP</EventCode>
          <CommandKey></CommandKey>
        </EventStruct>
      </Event>
      <MaxEnvelopes>0</MaxEnvelopes>
      <CurrentTime>2013-06-07 07:16:54.128 UTC</CurrentTime>
      <RetryCount>0</RetryCount>
      <ParameterList soapenc:arrayType="cwmp:ParameterValueStruct[1]">
        <ParameterValueStruct>
          <name>InternetGatewayDevice.DeviceInfo.SpecVersion</name>
          <value>1.0</value>
        </ParameterValueStruct>
      </ParameterList>
    </cwmp:Inform>
  </soap:Body>
</soap:Envelope>

我更多地研究了这个问题。我发现Xstream处理字段 Android上的订单错误。 Xstream在Java项目中很好地处理字段。

@XStreamAlias("cwmp:Inform")
public class Inform {
    @XStreamAlias("DeviceId")
    private DeviceIdStruct      deviceId;

    @XStreamAlias("Event")
    private EventList           event;

    @XStreamAlias("MaxEnvelopes")
    private int                 maxEnvelopes;

    @XStreamAlias("CurrentTime")
    private Date                currentTime;

    @XStreamAlias("RetryCount")
    private int                 retryCount;

    @XStreamAlias("ParameterList")
    private ParameterValueList  parameterList;
}

2 个答案:

答案 0 :(得分:2)

Here 是我的答案。
我研究了这个问题并得出结论,Android按字段类型的字母顺序返回字段。 您可以继承FieldKeySorter来设置顺序。

首先,您需要创建定义字段顺序的注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface XMLSequence {
    String[] value();
} 

使用示例:

@XMLSequence({
        "accountIds",
        "addresses",
        "birthDate",
        "contact",
        "name",
        "status",
}) 

然后我继承了FieldKeySorter:

public class SequenceFieldKeySorter implements FieldKeySorter {
    @Override
    public Map sort(final Class type, final Map keyedByFieldKey) {
        Annotation sequence = type.getAnnotation(XMLSequence.class);
        if (sequence != null) {
            final String[] fieldsOrder = ((XMLSequence) sequence).value();
            Map result = new OrderRetainingMap();
            Set<Map.Entry<FieldKey, Field>> fields = keyedByFieldKey.entrySet();
            for (String fieldName : fieldsOrder) {
                if (fieldName != null) {
                    for (Map.Entry<FieldKey, Field> fieldEntry : fields) {
                        if
(fieldName.equals(fieldEntry.getKey().getFieldName())) {
                            result.put(fieldEntry.getKey(),
fieldEntry.getValue());
                        }
                    }
                }
            }
            return result;
        } else {
            return keyedByFieldKey;
        }

    }
}

最后去:

XStream x = new XStream(new PureJavaReflectionProvider(
new FieldDictionary(new SequenceFieldKeySorter()))); 

答案 1 :(得分:1)

  1. 您可以为要控制订单的类实现此接口FieldKeySorter
  2. 您可以自己编写注释,它不仅可以扩展目标类,还可以在运行时通过反射实现FieldKeySorter。最后替换实例以控制订单。