Android: 使用XStream解析.Net后台序列化的XML

因业务需要在Android端解析.net后台接口传递的XML,由于Android精简了jdk,无法使用原生XMLDecoder,因此选择了XStream实现。

C#后台使用原生XmlSerializer序列化

    public static string Serialize(object data)
    {
        string result = string.Empty;
        try
        {
            using (MemoryStream ms = new MemoryStream())
            {
                XmlSerializer xml = new XmlSerializer(data.GetType());
                xml.Serialize(ms, data);
                byte[] arr = ms.ToArray();
                result = Encoding.UTF8.GetString(ms.ToArray());
                ms.Close();
            }
        }
        catch (Exception ex)
        {
            throw;
        }
        return result;
    }


移动端使用XStream对接口返回的XML进行解析,注意的是如果序列化的实体类中的字段包含其它实体类,解析时需要为其设置对应类的别名,下面通过反射获取这些类

/**
     * XML 反序列化
     *
     * @param xmlStr  XML 字符串
     * @param classes alias
     */
    public static  T decode(String xmlStr, Class... classes) {
        XStream xStream = new XStream(new DomDriver());
        //这里添加子节点bean的别名
        for (Class clazz : classes) {
            xStream.alias(clazz.getSimpleName(), clazz);
        }
        //忽略未知节点
        xStream.ignoreUnknownElements();
        //因为需要将C# decimal类型转换为Java BigDecimal,这里需要对空值进行处理
        xStream.registerConverter(new BigDecimalConverter() {
            @Override
            public Object fromString(String str) {
                if (str == null || str.trim().length() == 0) {
                    return null;
                } else {
                    return new BigDecimal(str);
                }
            }
        });
        //添加类型安全配置,这里允许访问bean包下所有类
        xStream.allowTypesByWildcard(new String[]{"bean.**"});
        Object obj = xStream.fromXML(xmlStr);
        try {
            return (T) obj;
        } catch (ClassCastException e) {
            e.printStackTrace();
            return null;
        }
    }

通过反射获取实体类本身包含的其它实体类

    /**
     * 查找 Class 包含的所有 bean
     * 如果 Class 本身也是 Bean, 返回的 Set 会包含它本身
     *
     * @param clazz clz
     * @return class set
     */
    public static Set getAllBeanTypes(Class clazz) {
        if (clazz == null) {
            return null;
        }
        Set types = new HashSet<>();
        Class c = getBeanClassByName(clazz.getSimpleName());
        if (c != null) {
            types.add(c);
        }
        for (Class tempClz = clazz; tempClz != Object.class; tempClz = tempClz.getSuperclass()) {
            Field[] fields = tempClz.getDeclaredFields();
            for (Field field : fields) {
                if (field.getType() == List.class) {
                    Type type = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
                    if (getBeanClassByName(((Class) type).getSimpleName()) != null) {
                        types.add(((Class) type));
                        types.addAll(getAllBeanTypes(((Class) type)));
                    }
                } else if (getBeanClassByName(field.getType().getSimpleName()) != null) {
                    types.add(field.getType());
                    types.addAll(getAllBeanTypes(field.getType()));
                }
            }
        }
        return types;
    }

    public static Class getBeanClassByName(String name){
        Class clazz = null;
        try {
            clazz = Class.forName("bean." + name);
        } catch (ClassNotFoundException e) {
            //no need to print.
        }
        return clazz;
    }

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注