【问题标题】:XStream serialize null valuesXStream 序列化空值
【发布时间】:2012-10-25 10:14:49
【问题描述】:

假设我有

class Student
{
String name;
int    age;
String teacher;
}

然后:

public class App1
{
    public static void main(String[] args)
    {
        Student st = new Student();
        st.setName("toto");

        XStream xs = new XStream();

        xs.alias("student",Student.class);

        System.out.println(xs.toXML(st));
    }

}

给我:

<student>
  <name>toto</name>
  <age>0</age>
</student>

有没有办法处理空值?我的意思是:

<student>
  <name>toto</name>
  <age>0</age>
  <teacher></teacher>
</student>

如果我这样做是可能的

st.setTeacher("");

但如果教师为空,则不是。

我尝试使用自定义转换器,但似乎空值未发送到转换器。

【问题讨论】:

    标签: java serialization xstream


    【解决方案1】:

    我正在使用 XStream 1.4.7,@XStreamAlias 注释用于自定义字段名称,@XStreamConverter 用于自定义转换器(表示日期和其他自定义 bean)。但是,甚至没有调用空值的自定义转换器。 我的目标是序列化对象的所有字段,包括空字段,我不需要解组 XML。

    我设法通过创建自定义 ReflectionConverter 来做到这一点。 我从 XStream 库扩展了 ReflectionConverter 并覆盖了 doMarshal 方法。我唯一改变的是为 null info.values 调用 writeField 方法:

    new Object() {
    {
        for (Iterator fieldIter = fields.iterator(); fieldIter.hasNext();) {
            FieldInfo info = (FieldInfo) fieldIter.next();
            if (info.value != null) {
                //leave the code unchanged
                ...
            } else {
                //add this to write null info.value to xml
                Log.info("MyCustomReflectionConverter -> serialize null field: " + info.fieldName);
                writeField(info.fieldName, null, info.type, info.definedIn, info.value);
            }
        }
        //... leave the rest of the code unchanged
    }
    };
    

    之后,我创建了这样的 xStream 实例(以非常低的优先级注册您的转换器非常重要):

    StaxDriver driver = new StaxDriver(new NoNameCoder()) {
        @Override
        public StaxWriter createStaxWriter(XMLStreamWriter out) throws XMLStreamException {
            // the boolean parameter controls the production of XML declaration
            return createStaxWriter(out, false);
        }
    };
    
    XStream xStream = new XStream(driver);
    xStream.autodetectAnnotations(true);//needed to process aliases
    //register MyCustomReflectionConverter
    MyCustomReflectionConverter reflectionConverter = new MyCustomReflectionConverter (xStream.getMapper(), new SunUnsafeReflectionProvider());
    xStream.registerConverter(reflectionConverter, XStream.PRIORITY_VERY_LOW);
    

    感谢 Mark Nabours 的解决方案here

    希望对您有所帮助。有没有人为此找到更好的解决方案?

    【讨论】:

    • 这里的链接坏了
    【解决方案2】:

    首先在Student类中提供getter和setter方法如下:

    public class Student{
       String name;
       int age;
       String teacher;
       public void setName(String name){
           this.name = name;
       }
       public String getName(){
          return name;
       }
    .......
    ......//Like that mention other getter and setter method
    }
    

    现在,您只需按如下方式创建转换器类:

    public class StudentConverter implements Converter{
        public boolean canConvert(Class clazz) {
             return clazz.equals(Test.class);
        }
        public void marshal(Object value, HierarchicalStreamWriter writer,
             MarshallingContext context) {
           Student student = (Student ) value;
           writer.startNode("name");
           writer.setValue(test.getName());
           writer.endNode();
           writer.startNode("age");
           writer.setValue(test.getAge());
           writer.endNode();
           writer.startNode("teacher");
           writer.setValue("");
           writer.endNode();
       }
        public Object unmarshal(HierarchicalStreamReader reader,
             UnmarshallingContext context) {
           Student student = new Student();
           test.setName(reader.getNodeName());
           test.setAge(reader.getNodeName());
           test.setTeacher(reader.getNodeName());
           return student;
        }
    }
    
    Your main class will the like that:
    
    public class App1{
        public static void main(String args[]) {
            XStream stream = new XStream(new StaxDriver());
            Student st = new Student();
            st.setName("ABC");
            t.setAge(21);
            stream.registerConverter(new StudentConverter());
            stream.alias("student", Student.class);
            System.out.println(stream.toXML(st));
       }
    
    }
    

    希望这是你的答案....学习愉快:)

    【讨论】:

      【解决方案3】:

      你可以放一个空字符串

      String teacher = "";
      

      或者优化一个:)

      String teacher = StringUtils.EMPTY;
      

      【讨论】:

        猜你喜欢
        • 2012-04-22
        • 2012-02-25
        • 2010-12-16
        • 1970-01-01
        • 2013-04-02
        • 2014-10-25
        • 1970-01-01
        • 1970-01-01
        • 2013-07-02
        相关资源
        最近更新 更多