在 JSON 转换为 CSV 期间保持 JSON 密钥的顺序

2022-08-31 11:13:58

我正在使用此处提供的JSON库 http://www.json.org/java/index.html 将我必须的json字符串转换为CSV。但我遇到的问题是,转换后键的顺序丢失了。

这是转换代码:

    JSONObject jo = new JSONObject(someString);
    JSONArray ja = jo.getJSONArray("items");
    String s = CDL.toString(ja);
    System.out.println(s);

这是“一些弦”的内容:

{
    "items":
    [
        {
            "WR":"qwe",
            "QU":"asd",
            "QA":"end",
            "WO":"hasd",
            "NO":"qwer"
        },
    ]
}

结果如下:

WO,QU,WR,QA,NO
hasd,asd,qwe,end,qwer

虽然我期望的是保持键的顺序:

WR,QU,QA,WO,NO
qwe,asd,end,hasd,qwer

有没有办法使用此库获得此结果?如果没有,是否有任何其他库可以提供在结果中保持键顺序的功能?


答案 1

有(黑客)方法来做到这一点...但你不应该。

在 JSON 中,对象的定义如下:

对象是一组无序的名称/值对。

请参见 http://json.org

JSON的大多数实现都不会努力保持对象的名称/值对的顺序,因为它(根据定义)并不重要。

如果你想保留顺序,你需要重新定义你的数据结构;例如:

{
    "items":
    [
        [
            {"WR":"qwe"},
            {"QU":"asd"},
            {"QA":"end"},
            {"WO":"hasd"},
            {"NO":"qwer"}
        ],
    ]
}

或者更简单地说:

{
    "items":
    [
        {"WR":"qwe"},
        {"QU":"asd"},
        {"QA":"end"},
        {"WO":"hasd"},
        {"NO":"qwer"}
    ]
}

随访

感谢您的信息,但我别无选择,只能在我的应用程序中使用JSON,我的应用程序需要保持密钥的顺序,而不管JSON对象的定义如何...我也不允许更改JSON文件的格式...

您需要与设计该文件结构的人进行艰苦的对话,并且不允许您更改它。这是/他们是完全错误的。你需要说服他们。

如果他们真的不让你改变它:

  • 你应该坚持称它为JSON ...“因为事实并非如此。
  • 您应该指出,您将不得不专门编写/修改代码来处理这种“非JSON”格式...除非你能找到一些保持顺序的JSON实现。如果他们是付费客户,请确保他们为您必须做的额外工作付费。
  • 你应该指出,如果“不是JSON”需要由其他工具使用,那将是有问题的。事实上,这个问题会一遍又一遍地发生...

这种事情真的很糟糕。一方面,您的软件将违反旨在促进互操作性的既定/长期存在的规范。另一方面,设计这种蹩脚(不是JSON!)文件格式的机智者可能会从其他人的系统上脱落,因为系统无法应对他们的胡说八道。

更新

同样值得一读的是JSON RFC(RFC 7159)关于这个主题的内容。以下是一些摘录:

自RFC 4627发布以来的几年中,JSON已被广泛使用。这种经验揭示了某些模式,这些模式虽然是其规范所允许的,但导致了互操作性问题。

JavaScript 对象表示法 (JSON) 是一种用于序列化结构化数据的文本格式。...

JSON 可以表示四种基元类型(字符串、数字、布尔值和 null)和两种结构化类型(对象和数组)。

对象是零个或多个名称/值对的无序集合,其中名称是字符串,值是字符串、数字、布尔值、null、对象或数组。

已经观察到JSON解析库在它们是否使对象成员的排序对调用软件可见方面存在差异。其行为不依赖于成员排序的实现将是可互操作的,因为它们不会受到这些差异的影响。


答案 2

维持秩序非常简单。我在维护从数据库层到UI层的顺序时遇到了同样的问题。

打开 JSONObject.java 文件。它在内部使用HashMap,它不维护顺序。

将其更改为LinkedHashMap:

    //this.map = new HashMap();
    this.map = new LinkedHashMap();

这对我有用。在评论中让我知道。我建议JSON库本身应该有另一个JSONObject类来维护顺序,比如JSONOrderdObject.java。我在选择名字方面非常糟糕。