Java/Android中JSONObject转JSONArray并统一键名为open的方法
Java/Android 基于LinkedHashMap的JSON结构转换实现
初始处理代码
通过LinkedHashMap对原始JSONArray做分组累加的实现如下:
Map<String, Integer> map = new LinkedHashMap<>(); for (int j = 0; j < jsonArray.length(); j++) { JSONObject list = jsonArray.getJSONObject(j); String key = list.getString("symbol") + list.getString("groupname"); if (!map.containsKey(key)) { map.put(key, list.getInt("openqty")); } else { int val = map.get(key) + list.getInt("openqty"); map.put(key, val); } System.out.println("map " + map); } // Converted map into jsonstring String jsonString = new JSONObject(map).toString(); System.out.println("jsonstring " + jsonString);
初始运行输出
上述代码运行后生成的JSONObject由LinkedHashMap转换得到,键为symbol与groupname拼接的自定义字符串,值为累加后的openqty数值,输出如下:
{"SILVERRohit":0,"DINRCosmic":20,"NATURALGASCosmic":0,"NGCosmic":0,"SICosmic":-5,"SILVERCosmic":35,"DINRRishi":0,"SIRishi":0,"SILVERRishi":0,"CLAmitTA":-6, "CRUDEOILAmitTA":60,"DINRAmitTA":24,"GCAmitTA":0,"GOLDAmitTA":0,"SIAmitTA":0,"SILVERAmitTA":0,"DINRPraveen":0,"GCPraveen":0,"GOLDPraveen":0,"DINRHarsh":46, "GCHarsh":-9,"GOLDHarsh":28,"SIHarsh":9,"SILVERHarsh":-45,"DINRGovind":-160,"SIGovind":11}
转换需求
需要将上述结果转换为JSONArray格式,作为RecyclerView的绑定数据源,要求:
- 解决此前遍历转换时出现的列表行数据值重复问题
- 转换后JSONArray中所有子JSONObject的键统一替换为自定义键名
open - 最终输出结构符合如下预期:
[ {"open":0},{"open":20} , {"open":0} , {"open":0} ,{"open":-5 } , {"open":35 } , {"open":0} ,{"open":0 },{"open":0 } ,{"open":-6 }, {"open":60},{"open":24},{"open":0},{"open":0},{"open":0}, {"open":0},{"open":0},{"open":0},{"open":0},{"open":46}, {"open":-9},{"open":28},{"open":9},{"open":-45}, {"open":-160},{"open":11} ]
正确实现代码
之前遍历出现值重复的核心原因是:将子JSONObject实例的创建写在了循环外部,导致数组中所有元素都引用同一个对象,最终所有元素的值都和最后一次循环的赋值一致。另外注意不要先把LinkedHashMap转成普通JSONObject再遍历,避免低版本Android下JSONObject不保序导致的数据顺序错乱,直接遍历LinkedHashMap的entrySet即可,实现代码如下:
JSONArray targetArray = new JSONArray(); // 直接遍历保序的LinkedHashMap,无需先转成JSONObject for (Map.Entry<String, Integer> entry : map.entrySet()) { // 每次循环必须新建JSONObject实例,禁止复用外部创建的对象 JSONObject item = new JSONObject(); try { item.put("open", entry.getValue()); targetArray.put(item); } catch (JSONException e) { e.printStackTrace(); } } // 输出验证最终结果 System.out.println("target array: " + targetArray.toString());
实现说明
- LinkedHashMap本身保留插入顺序,直接遍历可以保证数据顺序和之前累加的顺序完全一致
- 每次循环新建JSONObject实例,从根源解决对象复用导致的值重复问题
- 不需要额外做字符串解析、键名遍历等冗余操作,性能更高
内容的提问来源于stack exchange,提问作者Abhishek Tiwari
相关产品推荐
相关产品推荐

