2

我正在努力捕获标签中包含的元素的顺序。这是所有代码:

联盟.java:

@Root
@Convert(value = LeagueConverter.class)
public class League 
{
    @Attribute
    private String name;

    @Element(name="headlines", required = false)
    private Headlines headlines;

    @Element(name="scores", required = false)
    private Scores scores;

    @Element(name="standings", required = false)
    private Standing standings;

    @Element(name="statistics", required = false)
    private LeagueStatistics statistics;

    public List<String> order = new ArrayList<String>();

        // get methods for all variables
}

LeagueConverter.java:

public class LeagueConverter implements Converter<League>
{
       @Override
       public League read(InputNode node) throws Exception
       {
               League league = new League();
               InputNode next = node.getNext();
               while( next != null )
               {
                String tag = next.getName();
                if(tag.equalsIgnoreCase("headlines"))
                {
                  league.order.add("headlines");
                }
                else if(tag.equalsIgnoreCase("scores"))
                    {
                          league.order.add("scores");
                    }
                else if(tag.equalsIgnoreCase("statistics"))
                {
                  league.order.add("statistics");
                }
                else if(tag.equalsIgnoreCase("standings"))
                {
                  league.order.add("standings");
                }
                    next = node.getNext();
                }
                return league;
       }
   @Override
   public void write(OutputNode arg0, League arg1) throws Exception 
   {
    throw new UnsupportedOperationException("Not supported yet.");
   }
}

XML 示例:

 <android>
    <leagues>
       <league name ="A">
          <Headlines></Headlines>
          <Scores></Scores>
          ...
       </league>
       <league name ="B">...</league>
    </leagues>
 </android>

我如何称呼它并期望它的行为:(片段)

 Android android = null;
 Serializer serial = new Persister(new AnnotationStrategy());

 android = serial.read(Android.class, source);
 Log.i("Number of leagues found ",tsnAndroid.getLeagueCount() + ""); // prints fine
 League nhl = tsnAndroid.getLeagues().get(0); // works fine

 // DOES NOT WORK throws NullPointerEx
 League nhl2 = tsnAndroid.getLeagueByName("A");
 // DOES NOT WORK throws NullPointerEx

 for(String s : nhl.getOrder())
 {
    Log.i("ORDER>>>>>", s);
 }

问题:

android.getLeagueByName()(与@Attribute名称一起工作)当我设置转换器时突然停止工作,所以它就像下面的 from League.java,永远不会被设置。

@Attribute
private String name; // not being set

但是,当我注释掉转换器声明时League.java- 每个联赛都有一个名为 name 的属性并android.getLeagueByName()开始正常工作......

@Convert for League 是否会以某种方式干扰 League 中的 @Attribute?

4

3 回答 3

5

尽管这个问题非常古老(SimpleXML 库也是如此),但我还是愿意付出两分钱。

@Convert注解仅适用于@Element ,但对@Attribute没有任何影响。我不确定这是错误还是功能,但还有另一种处理自定义序列化对象的方法 - 称为Transform with Matcher,它适用于AttributesElements。您无需使用Converter,而是定义一个处理序列化和反序列化的Transform类:

import java.util.UUID;
import org.simpleframework.xml.transform.Transform;

public class UUIDTransform implements Transform<UUID> {
    @Override
    public UUID read(String value) throws Exception {
        return value != null ? UUID.fromString(value) : null;
    }
    @Override
    public String write(UUID value) throws Exception {
        return value != null ? value.toString() : null;
    }
}

如您所见,它比实现 Convert 接口更直接!

为所有需要自定义反序列化的对象创建一个类似的类。

现在实例化一个RegistryMatcher对象并在那里注册您的自定义类及其相应的Transform类。这是一个内部使用缓存的线程安全对象,因此将其保留为单例可能是个好主意。

private static final RegistryMatcher REGISTRY_MATCHER = new RegistryMatcher();
static {
    try {
        REGISTRY_MATCHER.bind(UUID.class, UUIDTransform.class);
        // register all your Transform classes here...
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

最后,您可以在每次转换之前创建一个Persister类,并将AnnotationStrategy与您的RegistryMatcher实例一起传递给它。在下面的这个工厂方法中,我们还将使用缩进格式化程序:

private static Persister createPersister(int indent) {
    return new Persister(new AnnotationStrategy(), REGISTRY_MATCHER, new Format(indent));
}

现在您可以制作序列化/反序列化方法:

public static String objectToXml(Object object, int indent) throws MyObjectConversionException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    Persister p = createPersister(indent);
    try {
        p.write(object, out, "UTF-8");
        return out.toString("UTF-8");
    } catch (Exception e) {
        throw new MyObjectConversionException("Cannot serialize object " + object + " to XML: " + e.getMessage(), e);
    }
}

public static <T> T xmlToObject(String xml, final Class<T> clazz) throws MyObjectConversionException {
    Persister p = createPersister(0);
    try {
        return (T) p.read(clazz, xml);
    } catch (Exception e) {
        throw new MyObjectConversionException(
                "Cannot deserialize XML to object of type " + clazz + ": " + e.getMessage(), e);
    }
}

这种方法的唯一问题是当您希望对同一对象使用不同的格式时 - 例如,一旦您希望java.util.Date仅具有日期组件,而稍后您还希望拥有时间组件。然后只需扩展Date类,将其命名为DateWithTime,并为其制作不同的Transform

于 2016-11-10T20:12:03.323 回答
1

@Convert注释仅适用于@Element字段。我@Attribute也在努力反对转换字段,但现在没有成功......

于 2014-03-12T10:50:04.697 回答
1

@ElementListUnion 将捕获元素的顺序

于 2013-07-17T08:57:51.973 回答