【问题标题】:Ignore whitespace while converting XML to JSON using XStream使用 XStream 将 XML 转换为 JSON 时忽略空格
【发布时间】:2013-03-16 14:26:20
【问题描述】:

我正在尝试建立一种使用 Java 将 XML 转换为 JSON 的可靠且快速的方法,并且我已经开始使用 XStream 来执行此任务。但是,当我运行下面的代码时,由于空格(包括换行符)而导致测试失败,如果我删除这些字符,那么测试将通过。

    @Test
    public void testXmlWithWhitespaceBeforeStartElementCanBeConverted() throws Exception {
        String xml =
                "<root>\n" +
                "   <foo>bar</foo>\n" + // remove the newlines and white space to make the test pass
                "</root>";
        String expectedJson = "{\"root\": {\n" +
                "  \"foo\": bar\n" +
                "}}";
        String actualJSON = transformXmlToJson(xml);

        Assert.assertEquals(expectedJson, actualJSON);
    }

    private String transformXmlToJson(String xml) throws XmlPullParserException {
        XmlPullParser parser =  XppFactory.createDefaultParser();
        HierarchicalStreamReader reader = new XppReader(new StringReader(xml), parser, new NoNameCoder());
        StringWriter write = new StringWriter();
        JsonWriter jsonWriter = new JsonWriter(write);
        HierarchicalStreamCopier copier = new HierarchicalStreamCopier();
        copier.copy(reader, jsonWriter);
        jsonWriter.close();
        return write.toString();
    }

测试失败异常:

com.thoughtworks.xstream.io.json.AbstractJsonWriter$IllegalWriterStateException: Cannot turn from state SET_VALUE into state START_OBJECT for property foo
    at com.thoughtworks.xstream.io.json.AbstractJsonWriter.handleCheckedStateTransition(AbstractJsonWriter.java:265)
    at com.thoughtworks.xstream.io.json.AbstractJsonWriter.startNode(AbstractJsonWriter.java:227)
    at com.thoughtworks.xstream.io.json.AbstractJsonWriter.startNode(AbstractJsonWriter.java:232)
    at com.thoughtworks.xstream.io.copy.HierarchicalStreamCopier.copy(HierarchicalStreamCopier.java:36)
    at com.thoughtworks.xstream.io.copy.HierarchicalStreamCopier.copy(HierarchicalStreamCopier.java:47)
    at testConvertXmlToJSON.transformXmlToJson(testConvertXmlToJSON.java:30)

有没有办法告诉复制过程忽略可忽略的空白。我找不到任何明显的方法来启用这种行为,但我认为它应该在那里。我知道我可以预处理 XML 以删除空白,或者只是使用另一个库。

更新 我可以使用 HierarchicalStreamReader 接口的装饰器并手动抑制空白节点来解决该问题,但这仍然感觉不理想。这看起来像下面的代码,这将使测试通过。

    public class IgnoreWhitespaceHierarchicalStreamReader implements HierarchicalStreamReader {
        private HierarchicalStreamReader innerHierarchicalStreamReader;

        public IgnoreWhitespaceHierarchicalStreamReader(HierarchicalStreamReader hierarchicalStreamReader) {
            this.innerHierarchicalStreamReader = hierarchicalStreamReader;
        }

        public String getValue() {
            String getValue = innerHierarchicalStreamReader.getValue();
            System.out.printf("getValue = '%s'\n", getValue);
            if(innerHierarchicalStreamReader.hasMoreChildren() && getValue.length() >0)         {
                if(getValue.matches("^\\s+$")) {
                    System.out.printf("*** White space value suppressed\n");
                    getValue = "";
                }
            }
            return getValue;
        }
        // rest of interface ...

感谢任何帮助。

【问题讨论】:

    标签: java xml json xstream


    【解决方案1】:

    比较两个 XML 为 String 对象不是一个好主意。当xml相同但节点顺序不同时,您将如何处理?

    例如

    <xml><node1>1</node1><node2>2</node2></xml>
    

    类似于

    <xml><node2>2</node2><node1>1</node1></xml>
    

    但是当你进行字符串比较时,它总是会返回 false。

    改为使用 XMLUnit 等工具。更多详情请参考以下链接,

    Best way to compare 2 XML documents in Java

    【讨论】:

    • 感谢您的回复,但我看不到在哪里执行 XML 比较。你的意思是在我删除空格的描述符中吗?
    • 我的意思是当你调用 Assert.assertEquals 时。这两个参数都是 String 对象,因此将调用 String.equals() 方法。相反,您必须创建 XMLObject 类覆盖它的 equals 方法来进行 XML 比较。
    • assertEquals 正在测试 JSON 字符串而不是 XML 字符串。我同意,如果 JSON 字符串的内容可能不准确,因此测试可能会因此失败(但我没有走那么远),我应该测试等效性。为了简洁起见,测试仅以这种方式显示,并不是引发异常的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    相关资源
    最近更新 更多