2015-04-22 10 views
5

Gibt es für einen lokalen Konverter beim Marshalling nach XML eine Möglichkeit, auf das übergeordnete Objekt zuzugreifen?XStream Elternobjekt im Konverter abrufen

Ich muss eine Sammlung mit Elementen aus einer Quelle von Drittherstellern marshall - mit einer ID im übergeordneten Objekt gespeichert.

Leider scheint es keine Möglichkeit zu geben, den Objektpfad abzufragen, der zum aktuellen Objekt führt. Oder ist es da?

+0

ich ein ähnliches Problem haben. Hast du eine Lösung gefunden? TIA – t777

+0

Ich habe es akzeptiert - weil es lange her ist. :-) –

Antwort

0

fand ich eine Lösung mit wenig reflaction:

import java.io.InputStream; 
import java.lang.reflect.Field; 
import java.util.List; 
import java.util.Map; 

import org.junit.Test; 
import org.springframework.util.ReflectionUtils; 

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.MarshallingContext; 
import com.thoughtworks.xstream.converters.UnmarshallingContext; 
import com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller; 
import com.thoughtworks.xstream.io.HierarchicalStreamReader; 
import com.thoughtworks.xstream.io.HierarchicalStreamWriter; 
import com.thoughtworks.xstream.io.path.Path; 

import lombok.Data; 

public class XStreamGetInfoFromParentTest { 

    @Test 
    public void smokeTest() { 
     InputStream file = XStreamGetInfoFromParentTest.class.getResourceAsStream("XStreamGetInfoFromParentTest.xml"); 

     XStream xStream = new XStream() { 
      @Override 
      public void registerConverter(Converter converter, int priority) { 
       Converter myConverter = new MyConverterWrapper(converter); 
       super.registerConverter(myConverter, priority); 
      } 
     }; 
     xStream.processAnnotations(Papa.class); 
     xStream.processAnnotations(Baby.class); 

     Papa papa = (Papa) xStream.fromXML(file); 

     System.out.println(papa); 
    } 

    public class MyConverterWrapper implements Converter { 

     private Converter converter; 
     private boolean isBabyClass; 

     public MyConverterWrapper(Converter converter) { 
      this.converter = converter; 
     } 

     @Override 
     public boolean canConvert(Class type) { 
      this.isBabyClass = type.equals(Baby.class); 
      return converter.canConvert(type); 
     } 

     @Override 
     public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { 
      this.converter.marshal(source, writer, context); 
     } 

     @SuppressWarnings({ "unchecked", "rawtypes" }) 
     @Override 
     public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 
      if (isBabyClass) { 
       AbstractReferenceUnmarshaller runm = (AbstractReferenceUnmarshaller) context; 

       Field field = ReflectionUtils.findField(AbstractReferenceUnmarshaller.class, "values"); 
       field.setAccessible(true); 
       Map values = (Map) ReflectionUtils.getField(field, runm); 

       values.forEach((key, value) -> { 
        System.out.println(key + " : " + value); 
       }); 

       Papa papa = (Papa) values.get(new Path("/papa")); 
       System.out.println(papa.firstname); 
      } 

      return converter.unmarshal(reader, context); 
     } 

    } 

    @XStreamAlias("papa") 
    @Data 
    public class Papa { 

     @XStreamAsAttribute 
     private String firstname; 

     private int age; 

     private List<Baby> babies; 

    } 

    @XStreamAlias("baby") 
    @Data 
    public class Baby { 
     private String firstname; 
    } 

} 

xml:

<?xml version="1.0" encoding="UTF-8"?> 
<papa firstname="Adam"> 
     <age>33</age> 
     <babies> 
      <baby> 
       <firstname>Eva</firstname> 
      </baby> 
     </babies> 
</papa>