2017-07-05 28 views
1

XMLファイルをデシリアライズする際に問題があります。同じ名前のノードをXStreamで2つの異なるクラスにデシリアライズする方法

私のファイルは次のようである:

<mission> 
    <branch> 
     <alternative uid="0" type="ALT_MONITOR"/> 
     <alternative uid="1" type="ALT_IF" condition="i==10"/> 
    </branch> 
</mission> 

私は代替というクラスがあります。

public abtract class Alternative { 
    @XStreamAsAttribute 
    public int uid; 
    @XStreamAsAttribute 
    public String type; 
} 

このクラスは、他の二つのクラスによって拡張されます。

@XStreamAlias("alternative") 
public class AlternativeA extends Alternative { 
} 

@XStreamAlias("alternative") 
public class AlternativeB extends Alternative { 
    @XStreamAsAttribute 
    public String condition; 
} 

し、私が持っているのxStreamコンバータ:

public class AlternativeConverter extends ReflectionConverter { 
    public AlternativesConverter(Mapper mapper, ReflectionProvider reflectionProvider) { 
     super(mapper, reflectionProvider); 
    } 

    @Override 
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 
    if (reader.getAttribute("condition") != null) { 
    AlternativeA alternativeA = new AlternativeA(); 
    alternativeA.setUid(Integer.parseInt(reader.getAttribute("uid"))); 
    alternativeA.setCondition(reader.getAttribute("condition")); 
    return super.doUnmarshal(alternativeA, reader, context); 
    }else { 
    AlternativeB alternativeB = new AlternativeB(); 
    alternativeB.setUid(Integer.parseInt(reader.getAttribute("uid"))); 
    return super.doUnmarshal(alternativeB, reader, context); 
    } 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public boolean canConvert(Class clazz) { 
     return Alternative.class.isAssignableFrom(clazz); 
    } 
} 

しかし、私はオブジェクトにxmlを変換しようとします。それが条件と代替に達すると、それは例外をスロー:あなたのいずれかがそのエラーを引き起こす可能性があるものにアイデアやint型を持っていますか

はAlternativeA

を入力するタイプのAlternativeBを変換することができませんか? ありがとうございます。

+0

クラスAlternativeAは何の条件属性を持っていません。 – Mark

答えて

1

のJava:

package de.mosst.spielwiese; 

import java.io.InputStream; 
import java.util.ArrayList; 
import java.util.List; 

import org.junit.Test; 

import com.thoughtworks.xstream.XStream; 
import com.thoughtworks.xstream.annotations.XStreamAlias; 
import com.thoughtworks.xstream.annotations.XStreamAsAttribute; 
import com.thoughtworks.xstream.converters.Converter; 
import com.thoughtworks.xstream.converters.UnmarshallingContext; 
import com.thoughtworks.xstream.converters.reflection.ReflectionConverter; 
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider; 
import com.thoughtworks.xstream.io.HierarchicalStreamReader; 
import com.thoughtworks.xstream.mapper.Mapper; 

import lombok.Data; 

public class XStreamMultiClassesTest { 

    @Test 
    public void smokeTest() { 
     InputStream file = XStreamMultiClassesTest.class.getResourceAsStream("XStreamMultiClassesTest.xml"); 
     XStream xStream = new XStream(); 
     xStream.ignoreUnknownElements(); 
     xStream.processAnnotations(Mission.class); 
     xStream.processAnnotations(Alternative.class); 

     Converter converter = new AlternativeConverter(xStream.getMapper(), xStream.getReflectionProvider()); 
     xStream.registerConverter(converter); 

     Mission mission = (Mission) xStream.fromXML(file); 

     System.out.println(mission); 
     mission.branch.forEach(a -> { 
      System.out.println(a.getClass()); 
      if (a instanceof AlternativeA) { 
       System.out.println("- condition: " + ((AlternativeA) a).condition); 
      } 
     }); 
    } 

    public class AlternativeConverter extends ReflectionConverter { 

     public AlternativeConverter(Mapper mapper, ReflectionProvider reflectionProvider) { 
      super(mapper, reflectionProvider); 
     } 

     @Override 
     public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 
      Alternative alternative = null; 
      if (reader.getAttribute("condition") != null) { 
       alternative = new AlternativeA(); 
       ((AlternativeA) alternative).condition = reader.getAttribute("condition"); 
      } else { 
       alternative = new AlternativeB(); 
      } 
      alternative.uid = Integer.parseInt(reader.getAttribute("uid")); 
      return super.doUnmarshal(alternative, reader, context); 
     } 

     @Override 
     public boolean canConvert(@SuppressWarnings("rawtypes") Class clazz) { 
      return Alternative.class.isAssignableFrom(clazz); 
     } 
    } 

    @XStreamAlias("mission") 
    @Data 
    class Mission { 
     public List<Alternative> branch = new ArrayList<>(); 
    } 

    @XStreamAlias("alternative") 
    @Data 
    abstract class Alternative { 
     @XStreamAsAttribute 
     public int uid; 
     @XStreamAsAttribute 
     public String type; 
    } 

    class AlternativeA extends Alternative { 
     public String condition; 
    } 

    class AlternativeB extends Alternative { 
    } 

} 

XML:

<?xml version="1.0" encoding="UTF-8"?> 
<mission> 
    <branch> 
     <alternative uid="0" type="ALT_MONITOR" /> 
     <alternative uid="1" type="ALT_IF" condition="i==10" /> 
    </branch> 
</mission> 
+0

あなたの答えをありがとう。私はそれを有効とマークしますが、私はそれをテストしませんでした。私はブランチのためのより高いレベルのコンバータを書いています。私は今のところうまくいく選択肢よりも多くのことを持つことができます。私のコードを扱うのがもっと複​​雑になるなら、私はあなたのソリューションを使ってみよう! –

関連する問題