Xstream處理XML產生中null值的複雜情況

來源:互聯網
上載者:User

前一段時間和Xstream打過交道,發現Xstream在支援json以及XML方面還是相當強大的。提供annotation註解,可以在JavaBean中完成對xml節點、屬性的描述。在根據xsd轉換為Xstream模型之後,希望利用Xstream來產生XML並且滿足XSD要求。例如:

package nju.software.ExecutionInterfaces.service.XstreamModels;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlRootElement;import javax.xml.bind.annotation.XmlType;import com.thoughtworks.xstream.annotations.XStreamAlias;@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "", propOrder = {    "userId",    "infoCode",    "departId"})@XmlRootElement(name = "info")@XStreamAlias("info")@Annotation(documentation="資訊")public class Info {    @XmlElement(name = "user_id")@XStreamAlias("user_id")@Annotation(documentation="使用者ID")    protected int userId;    @XmlElement(name = "info_code", required = true)@XStreamAlias("info_code")@Annotation(documentation="資訊密碼")    protected String infoCode;    @XmlElement(name = "depart_id", required = true, type = Integer.class, nillable = true)@XStreamAlias("depart_id")@Annotation(documentation="部門ID")    protected Integer departId;}

  根據XSD產生的模型加上Xstream註解。利用xStream中toXML()方法將Model轉換成XML字串。預想是僅僅使用processAnnotations方式注入註解就自動將XML中節點名稱寫好。但是產生的XML卻無法通過XSD的驗證。經過檢查發現是xsd中類型設定的原因。比如departId欄位。required = true, type = Integer.class, nillable = true,表示為Integer類型且可為空白。但是當真正將值設為空白時又通不過驗證。因為XSD在檢查數字類型的時候需要至少寫一個0。<depart_id/>或者<depart_id></depart_id>都不行。於是想到了使用Xstream中的Converter介面。在園子裡也看到了有關nullConverter的說明。在其基礎上進行了修改。

import java.lang.reflect.Field;import java.lang.reflect.Method;import java.math.BigDecimal;import java.text.DecimalFormat;import java.util.List;import com.thoughtworks.xstream.annotations.XStreamAlias;import com.thoughtworks.xstream.converters.Converter;import com.thoughtworks.xstream.converters.MarshallingContext;import com.thoughtworks.xstream.converters.UnmarshallingContext;import com.thoughtworks.xstream.io.HierarchicalStreamReader;import com.thoughtworks.xstream.io.HierarchicalStreamWriter;public class NullConverter implements Converter {@SuppressWarnings("unchecked")public void marshal(Object source, HierarchicalStreamWriter writer,MarshallingContext context) {if (null == source)return;Class cType = source.getClass();Field[] fields = cType.getDeclaredFields();if (source instanceof List) {List list = (List) source;for (Object obj : list) {XStreamAlias alias = obj.getClass().getAnnotation(XStreamAlias.class);if (alias != null) {writer.startNode(alias.value());marshal(obj, writer, context);writer.endNode();}else {marshal(obj, writer, context);}}} else {for (Field field : fields) {//獲得get方法String temp1 = "get"+ field.getName().substring(0, 1).toUpperCase()+ field.getName().substring(1);Method m = null;try {m = cType.getMethod(temp1, null);} catch (SecurityException e1) {e1.printStackTrace();} catch (NoSuchMethodException e1) {e1.printStackTrace();}String methodName = m.getName();if (methodName.indexOf("get") != -1 && methodName != "getClass") {boolean isBaseType = isBaseType(m.getReturnType());String name = methodName.substring(3);Object o = null;try {o = m.invoke(source, null);} catch (Exception e) {e.printStackTrace();}//遞迴打出基礎類型值if (isBaseType) {writer.startNode(getAliasByNameAndType(name, cType).value());writeData(o, m.getReturnType(), writer);writer.endNode();} else {XStreamAlias alias = getAliasByNameAndType(name, cType);if (alias == null) {marshal(o, writer, context);} else {writer.startNode(alias.value());marshal(o, writer, context);writer.endNode();}}}}}}/** * 根據Name和類獲得Xstream註解 * @param name * Name * @param cType * 類 * @return * XStreamAlias */private XStreamAlias getAliasByNameAndType(String name,Class<?> cType){String temp = name.substring(0, 1).toLowerCase()+ name.substring(1);Field f = null;try {f = cType.getDeclaredField(temp);} catch (SecurityException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();}XStreamAlias alias = f.getAnnotation(XStreamAlias.class);return alias;}/** * 改寫輸出XML * @param o * @param ReturnType * @param writer */private void writeData(Object o,Class<?> ReturnType,HierarchicalStreamWriter writer) {//如果是數字類型的話就要預設為0而不可為空if (isNumValueType(ReturnType)) {if (o == null) {writer.setValue("0");}else if (ReturnType.equals(Double.class)||ReturnType.equals(double.class)||ReturnType.equals(BigDecimal.class)) {DecimalFormat df = new DecimalFormat("#.##");writer.setValue(df.format(o));}else {writer.setValue(o.toString());}} else {writer.setValue(o == null ? "" : o.toString());}}public Object unmarshal(HierarchicalStreamReader reader,UnmarshallingContext context) {return null;}public boolean canConvert(Class type) {return true;}/** * 判斷是否為基本類型 * @param type * @return * boolean */private boolean isBaseType(Class<?> type) {if (type.equals(Integer.class) || type.equals(Double.class)|| type.equals(String.class) || type.equals(Boolean.class)|| type.equals(Long.class) || type.equals(Short.class)|| type.equals(Byte.class) || type.equals(Float.class)|| type.equals(BigDecimal.class) || type.equals(int.class)|| type.equals(float.class) || type.equals(long.class)|| type.equals(double.class) || type.equals(short.class)|| type.equals(boolean.class) || type.equals(byte.class)) {return true;}return false;}/** * 判斷是否為數字類型 * @param type * @return * boolean */public boolean isNumValueType(Class<?> type) {if (type.equals(Integer.class) || type.equals(Double.class)|| type.equals(Long.class) || type.equals(Short.class)|| type.equals(Float.class) || type.equals(BigDecimal.class)|| type.equals(int.class) || type.equals(float.class)|| type.equals(long.class) || type.equals(double.class)|| type.equals(short.class)) {return true;}return false;}}

  基本思想還是利用遞迴的思想,主要修改有這麼幾點:

1打出一個類中屬性XML節點的方式。原始方式是通過拼接出get方法,便利獲得屬性上的Xstream註解產生。但是這樣產生不能保證屬性的順序,於是改成getAliasByNameAndType方法中首先獲得屬性。根據屬性拼接get方法。

2由於需求原因增加了數字類型的判斷,並在輸出時也做了判斷。

這是第一次在園子裡發隨筆,寫的不好但是是想從現在開始記錄自己的學習生活。想養成寫部落格的習慣。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.