属性名为数字的JSON映射DTO及转XML的解决方案问询
可行解决方案有两种,均可满足你的需求:
方案1:基于org.json库实现递归重命名数字键(适配你现有代码栈)
你原有代码存在两个问题:
- 直接赋值
newPayload = payload属于引用传递,两个变量指向同一个JSONObject实例,遍历过程中删除key会触发ConcurrentModificationException- 未对value做类型判断和递归处理,所以只能处理顶层节点的数字键
修复后的完整实现如下,可递归处理所有层级的数字键:
import org.json.JSONArray; import org.json.JSONObject; import org.json.XML; import org.apache.commons.lang3.StringUtils; public class NumericKeyProcessor { public static Object processNumericKeys(Object jsonNode) { // 处理JSON对象类型 if (jsonNode instanceof JSONObject) { JSONObject originalObj = (JSONObject) jsonNode; JSONObject processedObj = new JSONObject(); for (String key : originalObj.keySet()) { // 数字键增加前缀,避免XML标签非法 String newKey = StringUtils.isNumber(key) ? "element" + key : key; // 递归处理当前键对应的值 processedObj.put(newKey, processNumericKeys(originalObj.get(key))); } return processedObj; } // 处理JSON数组类型 else if (jsonNode instanceof JSONArray) { JSONArray originalArr = (JSONArray) jsonNode; JSONArray processedArr = new JSONArray(); for (int i = 0; i < originalArr.length(); i++) { processedArr.put(processNumericKeys(originalArr.get(i))); } return processedArr; } // 普通值类型直接返回 else { return jsonNode; } } // 直接调用本方法即可完成JSON转XML public static String jsonToXml(String rawJson) { JSONObject originalJson = new JSONObject(rawJson); JSONObject processedJson = (JSONObject) processNumericKeys(originalJson); // 直接使用org.json自带工具转XML return XML.toString(processedJson); } }
使用时直接调用NumericKeyProcessor.jsonToXml(你的原始JSON字符串)即可拿到符合规范的XML内容,完全不需要做DTO映射,绕开数字无法作为类属性名的问题。
方案2:基于Jackson实现(适配主流Spring栈项目)
如果你的项目已经依赖Jackson,可使用以下实现,不需要额外引入org.json依赖:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import org.apache.commons.lang3.StringUtils; public class JacksonJsonToXmlConverter { private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); private static final XmlMapper XML_MAPPER = new XmlMapper(); private static JsonNode processKeys(JsonNode node) { if (node.isObject()) { ObjectNode originalObj = (ObjectNode) node; ObjectNode processedObj = JSON_MAPPER.createObjectNode(); originalObj.fields().forEachRemaining(entry -> { String newKey = StringUtils.isNumber(entry.getKey()) ? "element" + entry.getKey() : entry.getKey(); processedObj.set(newKey, processKeys(entry.getValue())); }); return processedObj; } else if (node.isArray()) { var processedArr = JSON_MAPPER.createArrayNode(); node.forEach(item -> processedArr.add(processKeys(item))); return processedArr; } return node; } public static String convert(String rawJson) throws Exception { JsonNode root = JSON_MAPPER.readTree(rawJson); return XML_MAPPER.writeValueAsString(processKeys(root)); } }
注意事项
- 键名前缀
element可根据业务需要自行修改,只要符合XML标签命名规则即可 - 两种方案均支持任意层级的嵌套JSON,不需要提前预知JSON结构
- 不需要做DTO映射,直接完成JSON到XML的转换,适配你当前无时间重构的场景
内容的提问来源于stack exchange,提问作者Mildfire
相关产品推荐
相关产品推荐

