Android - 简单的XML框架.@Convert干扰@Attribute - 如何解决这个问题?

ryv*_*ron 2 android converter xml-parsing simple-framework

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

League.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
}
Run Code Online (Sandbox Code Playgroud)

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.");
   }
}
Run Code Online (Sandbox Code Playgroud)

XML的例子:

 <android>
    <leagues>
       <league name ="A">
          <Headlines></Headlines>
          <Scores></Scores>
          ...
       </league>
       <league name ="B">...</league>
    </leagues>
 </android>
Run Code Online (Sandbox Code Playgroud)

我是如何调用它并期望它表现的:(片段)

 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);
 }
Run Code Online (Sandbox Code Playgroud)

问题:

android.getLeagueByName()(使用@Attribute名称)当我有转换器设置时突然停止工作,所以它像下面这样League.java,永远不会被设置.

@Attribute
private String name; // not being set
Run Code Online (Sandbox Code Playgroud)

然而,当我在转发器声明中注释掉League.java- 每个联盟都有一个名为name的属性并且android.getLeagueByName()开始正常工作......

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

小智 5

虽然这个问题非常古老(就像SimpleXML库一样),但我会给出两分钱.

@Convert注释仅适用于@Element,但它对@Attribute没有任何影响.我不确定这是一个错误还是一个功能,但还有另一种处理自定义序列化对象的方法 - 名为Transform with Matcher,它既适用于Attributes,也适用于Elements.您可以定义一个处理序列化和反序列化的Transform类,而不是使用Converter ;

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

为需要自定义de/serialization的所有对象创建一个类似的类.

现在实例化一个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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

private static Persister createPersister(int indent) {
    return new Persister(new AnnotationStrategy(), REGISTRY_MATCHER, new Format(indent));
}
Run Code Online (Sandbox Code Playgroud)

现在您可以进行序列化/反序列化方法:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方法的唯一问题是当你想要为同一个对象设置不同的格式时 - 例如,一旦你希望java.util.Date只有日期组件,稍后你也想拥有时间组件.然后只需扩展Date类,将其命名为DateWithTime,并为其创建不同的Transform.