2013-06-07 8 views
1

Мне нужно сгенерировать XML из java-объектов на Android. Узлы XML должны быть в определенной последовательности. Вот то, что я получил (эти поля, как в соответствии с алфавитным порядком):Как поле порядка аннотации при использовании XStream на Android?

<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; 
} 
+0

@ Ігар Цімошка Помогите мне? – Folee

ответ

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. Вы можете реализовать этот интерфейс FieldKeySorter для классов, которые вы хотите контролировать.
  2. Вы можете написать аннотацию самостоятельно, которая не только расширяет целевой класс, но и реализует FieldKeySorter во время выполнения путем отражения. Наконец, замените экземпляр, чтобы контролировать порядок.
Смежные вопросы