如何在Java中将类似XML的结构化对象转换为JSON字符串?

如何解决如何在Java中将类似XML的结构化对象转换为JSON字符串?

因此,我有一个XML结构化对象(Java),并且需要一些帮助将其转换为JSON字符串,而无需使用任何库并且以迭代的方式进行。

例如

<root>
    <a/>
    <b/>
    <a/>
    <a>
        <c/>
    <a/>
    <d>
        ...
    </d>
<root/>

哪些可以在类(Java)中表示:

class Element {
    String name; (root)
    List<Element> childs; (a,b,a,d)(i.e. direct childs)
}

并且应使用JSON:

{
  "root":{
           "a":[
                 {},{},{
                   "c":{}
                 }
               ],"b": {},"d": {
                 ...
                }
         }
}

深度可以是无限的(不是真的,但是可以非常深),并且JSON字符串不需要缩进或保持相同的顺序,只需要示例中有效的JSON。困难的事情(除非使其成为迭代解决方案)是在同一级别具有相同名称的几个元素应为JSON中的数组,因为当存在带有相同元素的元素时JSON不喜欢它在同一级别使用相同的名称

编辑: 如前所述,我不是在寻找图书馆。此外,你们中许多人提到的库都使用递归,这也不是我想要的。而且我不是在转换实际的XML,而是一个类似于XML结构的对象,即它可以与具有相同名称,相同级别,不同深度等的子元素嵌套在一起。例如在示例中。不过谢谢!

解决方法

我不确定“不使用任何库”是什么意思,也不确定“迭代”或“最佳”是什么意思。

XML和JSON具有不同的数据模型,并且没有完美的最佳方式将它们彼此转换。有许多不同的库可以很好地完成工作,但是它们都有局限性。您提到的困难之一是XML元素具有多个具有相同名称的子元素(例如<div>包含多个<p>元素)。乍一看,将<p>元素转换成数组是有道理的。但是,如果有一个<div>只有一个<p>的孩子,您该怎么办?每个转换器都可以找到针对此问题的不同答案,但没有一个是完美的。

说您不想使用任何库意味着您要编写自己的转换器。这不是一个疯狂的主意,因为您可以根据自己的特定数据模型的性质调整转换规则。然后,您可以确定“最佳”对您而言意味着什么。

但是您的问题确实似乎是“请告诉我应该应用哪种转换规则”,唯一的答案是,没有适合所有人的转换规则。

,

导入org.json.JSONObject;

JSONObject xmlJsonObj = XML.toJSONObject(new String(buf,“ utf-8”));

或尝试

XML.toJSONObject(xml_text).toString();

这两个都应该起作用。

从此处JSON JAR下载

,

Jackson是一个很好的库,可以用Java将XML转换为JSON。 请查看this Jackson教程。

,

Michael Kay是对的。您需要构建自己的算法来遍历您的特定结构以编写您的特定JSON。穿过树状结构是一种递归。当然,如果需要,可以将其转换为迭代形式,但是递归似乎更自然。无论如何,imo,最好使用基于流/事件/令牌的API来生成JSON,而不是使用任何对象映射器。例如,使用您的Element结构和简单的JSON解析器/生成器https://github.com/anatolygudkov/green-jelly

import org.green.jelly.AppendableWriter;
import org.green.jelly.JsonGenerator;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ToJson {
    static class Element {
        final String name;
        final List<Element> children = new ArrayList<>();

        Element(final String name) {
            this.name = name;
        }

        void toJson(final JsonGenerator generator) {
            toJson(generator,false);
        }

        private void toJson(final JsonGenerator generator,boolean isArray) {
            if (!isArray) {
                generator.objectMember(name);
            }
            generator.startObject();

            children.stream()
                    .collect(Collectors.groupingBy(element -> element.name,Collectors.toList()))
                    .forEach((name,groupedByNameElements) -> {
                        if (groupedByNameElements.size() == 1) {
                            groupedByNameElements.get(0).toJson(generator,false);
                            return;
                        }
                        generator.objectMember(name);
                        generator.startArray();
                        groupedByNameElements.stream().forEach(element -> element.toJson(generator,true));
                        generator.endArray();
                    }
            );

            generator.endObject();
        }
    }

    public static void main(String[] args) {
        final Element root = new Element("root");
        root.children.add(new Element("a"));
        root.children.add(new Element("b"));
        root.children.add(new Element("a"));
        final Element aWithChild = new Element("a");
        root.children.add(aWithChild);
        aWithChild.children.add(new Element("c"));
        final Element dWithChildren = new Element("d");
        root.children.add(dWithChildren);
        dWithChildren.children.add(new Element("e"));
        final Element eWithChildren = new Element("e");
        dWithChildren.children.add(eWithChildren);
        eWithChildren.children.add(new Element("f"));
        eWithChildren.children.add(new Element("f"));

        final StringWriter result = new StringWriter();

        final JsonGenerator generator = new JsonGenerator(false);
        generator.setOutput(new AppendableWriter<>(result));
        generator.startObject();
        root.toJson(generator);
        generator.endObject();
        generator.eoj();

        System.out.println(result);
    }
}

代码产生

{"root":{"a":[{},{},{"c":{}}],"b":{},"d":{"e":[{},{"f":[{},{}]}]}}}

还要注意,您的算法将取决于您的特定数据/元素结构。例如,您可以存储已经订购并按名称分组的子级,等等...

,

因此,以迭代方式将其转换为JSON字符串,我进行了一些修改/调整的预遍历。

首先创建一个帮助类,我们将其称为Node,该类用于遍历结构。因此,每个Element都将被包装在此类中。此类帮助我用某些值标记节点,并用相同的名称对元素进行分组,这将在后面详细介绍。

接下来的事情是使用两个数据结构,一个Set和一个Stack(或双端队列)。使用Set来跟踪经过/经过的节点,并使用Stack进行遍历(在下一次迭代中要遍历的下一个节点)。

然后,我将根元素包装为Node并将其推入堆栈,然后可以开始进行遍历(实际上,在开始遍历之前,我还添加了一个开头{)。在每次迭代中,子元素都被“分组”并包装为节点,然后被压入堆栈。 “分组”的意思是,如果有多个同名子元素,则将它们放在Node的列表中,并将该节点标记为列表。

将子元素推入堆栈后,我做了以下事情:

  1. 如果当前访问的节点未标记为列表的部分,我将:<name of the node/element> :附加到JSON字符串结果中。这是因为如果它是列表的 part ,则不应为每个节点打印出该名称,因为对于JSON中的数组,该名称仅应在开始时打印一次。例如:{{ 1}}。
  2. 如果当前访问的节点不是列表,则我将"array":[{...},..,{...}]附加到结果中,并且还附加字段/属性(如果有)。
  3. 否则,如果当前访问的节点一个列表,则我附加了{并将其每个分组的子元素包装为[,将其标记为列表的一部分,并将其推入堆栈(以这种方式标记它们有助于步骤1的下一次迭代。)
  4. 将当前访问的节点添加到集合中。

右括号呢?在每次迭代的开始,我使用Set来检查是否已经访问了当前(最上层/窥视)节点(请参阅上面的第4步),如果它只意味着一件事:是时候关闭并弹出堆栈了。如果该节点被标记为列表,我们将使用Nodes将其关闭,否则将使用]将其关闭。然后,如果未访问下一个节点(窥视),则表示我们正在“侧身”移动,应在结果后附加}。否则,如果堆栈为空,则附加最后一个结束,。然后,转到下一个迭代。

我知道这是一个很长的答案,伪代码可能会更好(或者我无法显示的实际代码……是的,它有效!),但是我试图尽我所能。此解决方案可能不适用于所有情况。例如,必须只有一个根元素(如XML)。但是,这为我工作。基本上,这是一个简单的预购遍历...感谢您的所有帮助,当然,如果有人有意见,更好的解决方案,或者某些情况下这可能行不通,我将非常高兴听到!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?