我正在使用http://www.json.org/java/index.html提供的JSON库将我拥有的json字符串转换为CSV.但我遇到的问题是,转换后键的顺序会丢失.
这是转换代码:
JSONObject jo = new JSONObject(someString);
JSONArray ja = jo.getJSONArray("items");
String s = CDL.toString(ja);
System.out.println(s);
Run Code Online (Sandbox Code Playgroud)
这是"someString"的内容:
{
"items":
[
{
"WR":"qwe",
"QU":"asd",
"QA":"end",
"WO":"hasd",
"NO":"qwer"
},
]
}
Run Code Online (Sandbox Code Playgroud)
这是结果:
WO,QU,WR,QA,NO
hasd,asd,qwe,end,qwer
Run Code Online (Sandbox Code Playgroud)
虽然我期望保持键的顺序:
WR,QU,QA,WO,NO
qwe,asd,end,hasd,qwer
Run Code Online (Sandbox Code Playgroud)
有什么方法可以使用这个库得到这个结果吗?如果没有,是否有任何其他库可以提供保持结果中键的顺序的功能?
Ste*_*n C 91
有(hacky)方法可以做到这一点......但你不应该这样做.
在JSON中,定义了一个对象:
对象是一组无序的名称/值对.
大多数JSON实现都不会保留对象名称/值对的顺序,因为它(根据定义)并不重要.
如果要保留订单,则需要重新定义数据结构; 例如
{
"items":
[
[
{"WR":"qwe"},
{"QU":"asd"},
{"QA":"end"},
{"WO":"hasd"},
{"NO":"qwer"}
],
]
}
Run Code Online (Sandbox Code Playgroud)
或更简单地说:
{
"items":
[
{"WR":"qwe"},
{"QU":"asd"},
{"QA":"end"},
{"WO":"hasd"},
{"NO":"qwer"}
]
}
Run Code Online (Sandbox Code Playgroud)
跟进
感谢您的信息,但我别无选择,只能在我的应用程序中使用JSON,我的应用程序需要保持密钥的顺序,而不管JSON对象的定义...我不允许更改JSON文件的格式还有......
您需要与设计该文件结构的任何人进行硬性对话,并且不允许您更改它.这是/他们是完全错误的.你需要说服他们.
如果他们真的不让你改变它:
这种事情真的很糟糕.一方面,您的软件将违反旨在促进互操作性的完善/长期规范.另一方面,设计这种蹩脚(不是JSON!)文件格式的笨蛋可能会扼杀其他人的系统等等,因为系统无法应对他们的废话.
UPDATE
值得一读的还有JSON RFC(RFC 7159)在这个主题上所说的内容.以下是一些摘录:
自RFC 4627发布以来的几年中,JSON已经被广泛使用.这种体验揭示了某些模式,虽然它们的规范允许,却导致了互操作性问题.
JavaScript Object Notation(JSON)是用于结构化数据序列化的文本格式....
JSON可以表示四种基本类型(字符串,数字,布尔值和null)和两种结构化类型(对象和数组).
对象是零个或多个名称/值对的无序集合,其中名称是字符串,值是字符串,数字,布尔值,空值,对象或数组.
已经观察到JSON解析库的不同之处在于它们是否使对象成员的排序对调用软件可见.其行为不依赖于成员排序的实现将是可互操作的,因为它们不会受到这些差异的影响.
小智 46
维护秩序非常简单.我在维护从DB层到UI层的顺序方面遇到了同样的问题.
打开JSONObject.java文件.它在内部使用HashMap,它不维护订单.
将其更改为LinkedHashMap:
//this.map = new HashMap();
this.map = new LinkedHashMap();
Run Code Online (Sandbox Code Playgroud)
这对我有用.请在评论中告诉我.我建议JSON库本身应该有另一个维护顺序的JSONObject类,比如JSONOrderdObject.java.我很难选择名字.
小智 21
JSONObject.java采取你通过的任何地图.它可能是LinkedHashMap或者仅在地图为空时TreeMap才会使用hashmap.
这是JSONObject.java将执行地图检查的类的构造函数.
public JSONObject(Map paramMap)
{
this.map = (paramMap == null ? new HashMap() : paramMap);
}
Run Code Online (Sandbox Code Playgroud)
所以在构建一个json对象构造之前LinkedHashMap,然后将它传递给这样的构造函数,
LinkedHashMap<String, String> jsonOrderedMap = new LinkedHashMap<String, String>();
jsonOrderedMap.put("1","red");
jsonOrderedMap.put("2","blue");
jsonOrderedMap.put("3","green");
JSONObject orderedJson = new JSONObject(jsonOrderedMap);
JSONArray jsonArray = new JSONArray(Arrays.asList(orderedJson));
System.out.println("Ordered JSON Fianl CSV :: "+CDL.toString(jsonArray));
Run Code Online (Sandbox Code Playgroud)
所以没有必要改变JSONObject.java课程.希望它对某人有帮助.
小智 13
对这类问题更详细但广泛适用的解决方案是使用一对数据结构:包含排序的列表和包含关系的映射.
例如:
{
"items":
[
{
"WR":"qwe",
"QU":"asd",
"QA":"end",
"WO":"hasd",
"NO":"qwer"
},
],
"itemOrder":
["WR", "QU", "QA", "WO", "NO"]
}
Run Code Online (Sandbox Code Playgroud)
您迭代itemOrder列表,并使用它们查找地图值.订购保留,没有kludges.
我多次使用过这种方法.
fab*_*abe 10
使用的另一个hacky解决方案反映:
JSONObject json = new JSONObject();
Field map = json.getClass().getDeclaredField("map");
map.setAccessible(true);//because the field is private final...
map.set(json, new LinkedHashMap<>());
map.setAccessible(false);//return flag
Run Code Online (Sandbox Code Playgroud)
解决了。
我使用这里的 JSON.simple 库https://code.google.com/p/json-simple/读取 JSON 字符串以保持键的顺序并使用这里的 JavaCSV 库http://sourceforge.net/ items/javacsv/转换为 CSV 格式。
| 归档时间: |
|
| 查看次数: |
139664 次 |
| 最近记录: |