xStream JSON - 如何处理空值

时间:2011-10-24 10:40:04

标签: java json null xstream

我有这个json的例子:

{
    "rows": [
        {
            "anaid": "1",
            "anaint": "123",
            "anastring": "-"
        },
        {
            "anaid": "2",
            "anaint": "-",
            "anastring": "Hello World"
        },
        {
            "anaid": "3",
            "anaint": "-",
            "anastring": "-"
        }
    ]
}

我班上的测试是:

  • int anaid
  • int anaint
  • String anastring

我的java代码:

XStream xstream = new XStream(new JettisonMappedXmlDriver());
xstream.alias("rows", Test.class);
ArrayList<Test> product = (ArrayList<Test>) xstream.fromXML(json);

因此字符“ - ”是我的json的空值。我无法更改代码来创建json,但我会处理“ - ”null值以正确使用我的xStream解析器。

3 个答案:

答案 0 :(得分:0)

使用自定义转换器。教程here

答案 1 :(得分:0)

根据XStream的文档和邮件列表,编组输出中不包含空值 - 可能是一种约定。

discussion帮助我弄清楚如何展示它们。简而言之,诀窍是Varun所说的:一个自定义转换器,用于扩展默认的ReflectionConverter。我们的想法是停止忽略空值事件并将它们写入输出。

以下是对我如何运作的详细解释。不幸的是我无法分发最终解决方案;我希望以下解锁很多,甚至导致在主树中集成。

<强>配方

以下是我的解决方案的要点,基于[1]和XStream 1.4.2:

  1. 扩展com.thoughtworks.xstream.converters.reflection.ReflectionConverter类。
  2. 覆盖doMarshal / 3方法。原始方法忽略空事件,因此不写入任何内容。新方法应该只接受那些事件并写下想要的东西(一个空节点,一个自闭节点)。
  3. 覆盖writeField / 5方法以写入空值节点。写什么取决于想要什么,应该委托给编写者对象。
  4. 扩展com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWritercom.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper类以提供自定义编写器。写下空值节点需要一种方法。
  5. 以非常低的优先级注册转换器(因为反射是基本的,并将接管其他转换器)。
  6. 有关方法的更多细节

    例如,可以扩展一个带有XStream的编写器并实现一个额外的接口:

    // Context of "MyReflectionConverter"'s doMarshal method.
    void writeField(...)
        if (newObj == null) {
            NullExtendedHierarchicalStreamWriterHelper.emptyNode(
                            writer.underlyingWriter(),
                            aliasName != null ? aliasName:
                                mapper.serializedMember(source.getClass(), fieldName),
                            fieldType);
        }
        else { // Rest of the original writeField method
        }
    }
    

    界面位于NullExtendedHierarchicalStreamWriter,向emptyNode添加ExtendedHierarchicalStreamWriter / 2方法。此方法将空值写为自闭节点(例如,对于XML <int value="num"/>,意味着num是一个空整数)。上面的代码段使用帮助器NullExtendedHierarchicalStreamWriterHelper获取此作者的实例,该帮助器本身是ExtendedHierarchicalStreamWriterHelper的简单扩展。请注意,传递给帮助程序的编写器是writer.underlyingWriter(),因为编写器被包装并且包装器不实现接口的null扩展 - 这意味着我的解决方案仍然是一个黑客攻击,直到进行更深入的集成。

    转换器的注册通常以这种方式完成:

    serializer = new XStream(new MyStreamDriver());
    
    MyReflectionConverter reflectionConverter = new
            MyReflectionConverter(serializer.getMapper(),
                                  serializer.getReflectionProvider());
    serializer.registerConverter(reflectionConverter, XStream.PRIORITY_VERY_LOW);
    

    Here是上述自定义反射转换器与原始代码的差异。请考虑这是一个不属于主树的扩展,并且它比原始代码测试的要少得多。到目前为止,它通过了测试套件的案例。

答案 2 :(得分:0)

对我来说,简单的方法是获取源代码,复制ReflexionConverted类和方法public void marshal(Object original,final HierarchicalStreamWriter writer,final MarshallingContext context)...

你有:

reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
    public void visit(String fieldName, Class fieldType, Class definedIn, Object newObj) {
        if (newObj != null) {
            ...
            complete the else method with your code...for example:

        } else {
            Object obj = new String("");

            writeField(fieldName, fieldType, definedIn, obj);
            seenFields.add(fieldName);

        }
    }
}