XStream 在转换器中获取父对象
XStream get parent object in converter
对于本地转换器,当编组到 XML 时,有没有办法访问父对象?
我需要使用存储在父对象中的 ID 来编组包含来自第三方来源的项目的集合。
唉,好像没有办法查询到当前对象的对象路径。还是有?
我找到了一个稍微反射的解决方案:
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>
对于本地转换器,当编组到 XML 时,有没有办法访问父对象?
我需要使用存储在父对象中的 ID 来编组包含来自第三方来源的项目的集合。
唉,好像没有办法查询到当前对象的对象路径。还是有?
我找到了一个稍微反射的解决方案:
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>