XStream pom依賴:
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.10</version> </dependency>
1、對象解析成xml字符串時下划線變成雙下划線
解決:
xStream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("_-", "_")));
或者
xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
2、Security framework of XStream not initialized, XStream is probably vulnerable
解決:
XStream.setupDefaultSecurity(xStream); xStream.allowTypesByWildcard(new String[] { "com.common.util.**" //你的包路徑 });
3、處理既有屬性又有值的情況
形如:<Query Code="1">select * from user</Query>
使用自定義轉換器實現,如下:
public class QueryConverter implements Converter { @Override public boolean canConvert(Class type) { return type.equals(Query.class); } /** * 將java對象轉為xml時使用 */ @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { Query query = (Query) source; // 設置屬性值 writer.addAttribute("Code", query.getCode()); // 設置文本值 writer.setValue(query.getText()); } /** * 將xml轉為java對象使用 */ @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { Query query = new Query(); query.setTransactionCode(reader.getAttribute("Code")); query.setText(reader.getValue()); return query; } }
之后通過注解@XStreamConverter(value = QueryConverter.class)
或代碼注冊轉換器使用:
xStream.registerConverter(new xxxConverter());
4、時間轉換器
字段為Date類型
public class DateConverter implements Converter { @Override public boolean canConvert(Class arg0) { return Date.class == arg0; } @Override public void marshal(Object arg0, HierarchicalStreamWriter arg1, MarshallingContext arg2) { } @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext arg1) { GregorianCalendar calendar = new GregorianCalendar(); //格式化當前系統日期 SimpleDateFormat dateFm = new SimpleDateFormat("yyyy-MM-dd"); try { calendar.setTime(dateFm.parse(reader.getValue())); } catch (ParseException e) { throw new ConversionException(e.getMessage(), e); } return calendar.getTime(); } }
使用:
@XStreamConverter(DateConverter.class) private Date beginTime;
屬性為Date類型處理SingleValueConverter
public class XStreamDateConverter implements SingleValueConverter { @Override public boolean canConvert(Class arg0) { return Date.class == arg0; } @Override public Object fromString(String arg0) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); try { return format.parse(arg0); } catch (ParseException e) { e.printStackTrace(); } return null; } @Override public String toString(Object arg0) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); try { return format.format((Date) arg0); } catch (Exception e) { e.printStackTrace(); } return ""; } }
之后將轉化加在Date屬性的字段上使用即可
@XStreamConverter(value=XStreamDateConverter.class) @XStreamAsAttribute private Date beginTime;
5、針對null值的字段也顯示在xml中處理
大概思路就是遍歷對象的所有的字段,若當前字段的值為null,則處理成空字符串,示例自定義轉換器如下:
public class FieldConverter implements Converter { /** * 日志記錄 */ private static final Logger LOGGER = LoggerFactory.getLogger(FieldConverter.class); /** * 時間格式 */ private String formatPattern; public FieldConverter() { } public FieldConverter(String formatPattern) { this.formatPattern = formatPattern; } @Override public boolean canConvert(Class type) { return true; } /** * 將java對象轉為xml時使用 */ @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { try { handleSource(source, writer); } catch (Exception e) { LOGGER.error("[FieldConverter] marshal 異常,{}", e); throw new IllegalArgumentException("轉換xml出錯"); } } /** * @description :處理對象為xml轉換 * @param source 對象源 * @param writer 流寫出對象 * @date 2019/9/29 18:48 * @modifier * @return void */ private void handleSource(Object source, HierarchicalStreamWriter writer) throws IllegalAccessException { try { Class<?> aClass = source.getClass(); Field[] declaredFields = aClass.getDeclaredFields(); for (Field currField : declaredFields) { currField.setAccessible(Boolean.TRUE); // 字段注解 boolean isAttr = currField.isAnnotationPresent(XStreamAsAttribute.class); boolean isXStreamAlias = currField.isAnnotationPresent(XStreamAlias.class); boolean isFieldValue = currField.isAnnotationPresent(FieldValue.class); // 當前字段值 Object curFieldValue = currField.get(source); // 字段別名 String xmlAlias; if (isXStreamAlias) { xmlAlias = currField.getAnnotation(XStreamAlias.class).value(); } else { xmlAlias = currField.getName(); } if (isAttr) { // 字段屬性 writer.addAttribute(xmlAlias, null == curFieldValue ? "" : String.valueOf(curFieldValue)); } else if (isFieldValue) { // 字段值 writer.setValue(String.valueOf(curFieldValue)); } else { // 字段簡單處理 boolean isBaseType = DomainUtil.isBaseType(currField.getType()); if (curFieldValue instanceof List) { List<Object> list = (List<Object>) curFieldValue; for (int i = 0; i < list.size(); i++) { writer.startNode(xmlAlias + i); Object curr = list.get(i); isBaseType = DomainUtil.isBaseType(curr.getClass()); if (null == curr || isBaseType) { writer.setValue(null == curr ? "" : String.valueOf(curr)); } else { handleSource(curr, writer); } writer.endNode(); } } else { // 開始節點 writer.startNode(xmlAlias); if (null == curFieldValue || isBaseType) { writer.setValue(null == curFieldValue ? "" : String.valueOf(curFieldValue)); } else if (currField.getType().equals(Date.class)) { //時間對象 SimpleDateFormat format = new SimpleDateFormat(formatPattern); writer.setValue(null == curFieldValue ? "" : format.format(curFieldValue)); } else { //對象類型 handleSource(curFieldValue, writer); } // 結束節點 writer.endNode(); } } } } catch (Exception e) { LOGGER.error("[FieldConverter] handleSource 異常,{}", e); throw e; } } /** * 將xml轉為java對象使用 */ @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { System.out.println("coming....."); return null; }