如何维护JSONObject的顺序

我正在使用JSONObject来删除JSON字符串中不需要的certin属性:

JSONObject jsonObject = new JSONObject(jsonString); jsonObject.remove("owner"); jsonString = jsonObject.toString(); 

它工作正常,但问题是JSONObject是“一个无序的名称/值对集合”,我想保持String在进行JSONObject操作之前的原始顺序。

知道怎么做吗?

你不能。

这就是为什么我们称之为无序的名称/值对集合

为什么你需要这样做,我不确定。 但是如果你想要订购,你将不得不使用json数组。

我最近遇到了同样的问题,只是将我们所有的测试(希望JSON属性的顺序相同)转换到另一个JSON库:

   org.codehaus.jettison jettison 1.3.5  

在内部,它使用LinkedHashMap,它维护属性的顺序。 这个库在function上等同于json.org,所以我没有看到任何理由不使用它,至少对于测试而言。

如果可以编辑服务器repose,则将其更改为JSON对象数组。

JSON:

 [ {PropertyName:"Date of Issue:",PropertyValue:"3/21/2011"}, PropertyName:"Report No:",PropertyValue:"2131196186"},{PropertyName:"Weight:",PropertyValue:"1.00"}, {PropertyName:"Report Type:",PropertyValue:"DG"} ] 

我在客户端(Android)使用JSONArray处理它:

 String tempresult="[{PropertyName:"Date of Issue:",PropertyValue:"3/21/2011"},PropertyName:"Report No:",PropertyValue:"2131196186"},PropertyName:"Weight:",PropertyValue:"1.00"},{PropertyName:"Report Type:",PropertyValue:"DG"}]" JSONArray array = new JSONArray(tempresult); for (int i = 0; i < array.length(); i++) { String key = array.getJSONObject(i).getString("PropertyName"); String value = array.getJSONObject(i).getString("PropertyValue"); rtnObject.put(key.trim(),value.trim()); //rtnObject is LinkedHashMap but can be any other object which can keep order. } 

这并不容易,主要的想法是使用LinkedHashMap,或者传入构造函数(JSONObject(Map map)),或者修改字节码来处理String参数(JSONObject(String source)),这是主要的用例。 我在oson中得到了一个解决方案:

  public static JSONObject getJSONObject(String source) { try { int lineNumberToReplace = 157; ClassPool classPool = ClassPool.getDefault(); CtClass ctClass = classPool.get("org.json.JSONObject"); if (ctClass.isFrozen() || ctClass.isModified()) { if (source == null) { return new JSONObject(); } else { return new JSONObject(source); } } ctClass.stopPruning(true); CtConstructor declaredConstructor = ctClass.getDeclaredConstructor(new CtClass[] {}); CodeAttribute codeAttribute = declaredConstructor.getMethodInfo().getCodeAttribute(); LineNumberAttribute lineNumberAttribute = (LineNumberAttribute)codeAttribute.getAttribute(LineNumberAttribute.tag); // Index in bytecode array where the instruction starts int startPc = lineNumberAttribute.toStartPc(lineNumberToReplace); // Index in the bytecode array where the following instruction starts int endPc = lineNumberAttribute.toStartPc(lineNumberToReplace+1); // Let's now get the bytecode array byte[] code = codeAttribute.getCode(); for (int i = startPc; i < endPc; i++) { // change byte to a no operation code code[i] = CodeAttribute.NOP; } declaredConstructor.insertAt(lineNumberToReplace, true, "$0.map = new java.util.LinkedHashMap();"); ctClass.writeFile(); if (source == null) { return (JSONObject) ctClass.toClass().getConstructor().newInstance(); } else { return (JSONObject) ctClass.toClass().getConstructor(String.class).newInstance(source); } } catch (Exception e) { //e.printStackTrace(); } if (source == null) { return new JSONObject(); } else { return new JSONObject(source); } } 

需要包含使用mvn的jar文件

  javassist javassist 3.12.1.GA  

从Android 20开始,JSONObject保留顺序,因为它使用LinkedHashMap来存储namevaluepairs。 Android 19及更低版本使用HashMap存储namevaluepairs。 因此,Android 19及以下版本不保留订单。 如果您使用的是20或更高版本,请不要担心,JSONObject将保留订单。 或者,改为使用JSONArray。

在JDK 8及更高版本中,我们可以使用JDK 8支持的nashorn引擎来实现 .Java 8支持使用js引擎来评估:

 String content = ..json content... String name = "test"; String result = (String) engine.eval("var json = JSON.stringify("+content+");" + "var jsResult = JSON.parse(json);" + "jsResult.name = \"" + name + "\";" + "jsResult.version = \"1.0\";" + "JSON.stringify( jsResult );" );