如何将TransactionId设为JSON数组元素的首个字段并调整顺序
如何在JSON数组对象首位置添加指定字段并保证顺序?
问题背景
我需要给JSON数组GoodsReceivalLine的每个对象添加随机UUID作为TransactionId字段,并将该字段放在对象的首位,但现有代码生成的JSON字段顺序混乱,达不到预期效果。
原始JSON
{ "ImportOperation": { "Lines": { "GoodsReceivalLine": [ { "ExtWarehouseId": "Warehouse1", "CustomData": { "Item": [ { "Key": { "string": "Type" }, "Value": { "string": "Move" } } ] }, "CustomAllocationData": { "Item": [ { "Key": { "string": "Grade" }, "Value": { "string": "002" } } ] } }, { "ExtWarehouseId": "Warehouse2", "CustomData": { "Item": [ { "Key": { "string": "Type" }, "Value": { "string": "Move" } } ] }, "CustomAllocationData": { "Item": [ { "Key": { "string": "Grade" }, "Value": { "string": "002" } } ] } } ] } } }
期望JSON
{ "ImportOperation": { "Lines": { "GoodsReceivalLine": [ { "TransactionId": "RAndom UUID VAlue", "ExtWarehouseId": "Warehouse1", "CustomData": { "Item": [ { "Key": { "string": "Type" }, "Value": { "string": "Move" } } ] }, "CustomAllocationData": { "Item": [ { "Key": { "string": "Grade" }, "Value": { "string": "002" } } ] } }, { "TransactionId": "RAndom UUID VAlue", "ExtWarehouseId": "Warehouse2", "CustomData": { "Item": [ { "Key": { "string": "Type" }, "Value": { "string": "Move" } } ] }, "CustomAllocationData": { "Item": [ { "Key": { "string": "Grade" }, "Value": { "string": "002" } } ] } } ] } } }
尝试的代码(字段顺序混乱)
JSONObject inputJo = new JSONObject((String)globalMap.get("row1.body")); JSONObject impOpJo = inputJo.getJSONObject("ImportOperation"); JSONObject linesJo = impOpJo.getJSONObject("Lines"); JSONArray goodsRecJa = linesJo.getJSONArray("GoodsReceivalLine"); for(int i = 0; i<goodsRecJa.length(); i++){ JSONObject tmpObj = goodsRecJa.getJSONObject(i); tmpObj.put("TransactionId", java.util.UUID.randomUUID().toString()) ; } System.out.println("*** Body : "+inputJo.toString());
问题原因
你使用的JSONObject(默认是org.json库的实现)内部基于哈希表存储键值对,属于无序集合。调用put方法添加新字段时,不会保留插入顺序,更无法自动将新字段放到首位。循环逻辑本身没有错误,问题出在JSON对象的无序特性上。
修正方案
要保证字段顺序,需使用有序的键值对结构来构建JSON对象,以下是两种基于现有代码的修正方式:
方式1:用LinkedHashMap重建有序对象
通过LinkedHashMap(有序哈希表)先存入TransactionId,再按原顺序存入原有字段,最后用该Map创建新的JSONObject替换原数组对象:
import java.util.Iterator; import java.util.LinkedHashMap; import org.json.JSONArray; import org.json.JSONObject; JSONObject inputJo = new JSONObject((String)globalMap.get("row1.body")); JSONObject impOpJo = inputJo.getJSONObject("ImportOperation"); JSONObject linesJo = impOpJo.getJSONObject("Lines"); JSONArray goodsRecJa = linesJo.getJSONArray("GoodsReceivalLine"); for(int i = 0; i < goodsRecJa.length(); i++){ JSONObject tmpObj = goodsRecJa.getJSONObject(i); // 创建有序Map,先放入目标字段 LinkedHashMap<String, Object> orderedMap = new LinkedHashMap<>(); orderedMap.put("TransactionId", java.util.UUID.randomUUID().toString()); // 遍历原有字段,按原顺序加入Map Iterator<String> keys = tmpObj.keys(); while(keys.hasNext()){ String key = keys.next(); orderedMap.put(key, tmpObj.get(key)); } // 用有序Map生成新的JSONObject,替换数组中的原对象 goodsRecJa.put(i, new JSONObject(orderedMap)); } System.out.println("*** Body : "+inputJo.toString());
方式2:使用org.json的有序构造方法(部分版本支持)
如果你的org.json版本支持,可以直接通过JSONObject(boolean ordered)构造有序对象,再依次添加字段:
import java.util.Iterator; import org.json.JSONArray; import org.json.JSONObject; JSONObject inputJo = new JSONObject((String)globalMap.get("row1.body")); JSONObject impOpJo = inputJo.getJSONObject("ImportOperation"); JSONObject linesJo = impOpJo.getJSONObject("Lines"); JSONArray goodsRecJa = linesJo.getJSONArray("GoodsReceivalLine"); for(int i = 0; i < goodsRecJa.length(); i++){ JSONObject tmpObj = goodsRecJa.getJSONObject(i); // 创建有序的JSONObject JSONObject orderedObj = new JSONObject(true); // 先添加TransactionId orderedObj.put("TransactionId", java.util.UUID.randomUUID().toString()); // 再添加原有所有字段 Iterator<String> keys = tmpObj.keys(); while(keys.hasNext()){ String key = keys.next(); orderedObj.put(key, tmpObj.get(key)); } // 替换原对象 goodsRecJa.put(i, orderedObj); } System.out.println("*** Body : "+inputJo.toString());
注意事项
- JSON规范本身不强制要求字段顺序,只有当对接的系统有特殊要求时,才需要保证顺序。
- 如果后续有更多复杂JSON操作,建议使用Jackson或Gson等现代JSON库,它们对有序对象的支持更灵活。
内容的提问来源于stack exchange,提问作者Java BEE
相关产品推荐
相关产品推荐

