dom4j从1.5.2升级至2.1.3后遇非法字符异常的解决问询
解决dom4j 2.1.3处理纯数字键JSON时的IllegalArgumentException问题
问题原因
dom4j 2.x版本开始严格遵循W3C XML规范,其中明确规定XML元素/属性名称不能以数字开头或为纯数字。而1.5.2版本的校验规则较为宽松,允许这类名称存在,所以升级后处理含纯数字键的JSON时触发IllegalArgumentException。
可行解决方案
1. 自定义名称校验器,放宽规则
dom4j支持自定义NameChecker来替换默认的严格校验逻辑,允许纯数字或数字开头的名称通过校验:
import org.dom4j.util.SimpleNameChecker; public class LenientNameChecker extends SimpleNameChecker { @Override public boolean isValidName(String name) { // 允许纯数字或数字开头的名称,保留其他原有校验规则 if (name != null && name.matches("^\\d+$|^\\d.*")) { return true; } return super.isValidName(name); } @Override public boolean isValidQName(String qualifiedName) { if (qualifiedName != null) { String localPart = qualifiedName.contains(":") ? qualifiedName.split(":")[1] : qualifiedName; if (localPart.matches("^\\d+$|^\\d.*")) { return true; } } return super.isValidQName(qualifiedName); } }
在初始化dom4j时设置这个自定义校验器:
import org.dom4j.DocumentFactory; // 全局设置自定义校验器 DocumentFactory factory = DocumentFactory.getInstance(); factory.setNameChecker(new LenientNameChecker()); // 后续所有dom4j操作使用这个factory实例
2. 预处理JSON,重命名纯数字键
在JSON数据进入dom4j处理前,自动给纯数字键添加前缀(比如num_),处理完成后如果需要再还原键名:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; public class JsonNumericKeyHandler { public static JsonNode renameNumericKeys(JsonNode node) { if (node.isObject()) { ObjectNode newObj = new ObjectMapper().createObjectNode(); node.fieldNames().forEachRemaining(key -> { JsonNode value = node.get(key); // 仅对纯数字键添加前缀 String newKey = key.matches("^\\d+$") ? "num_" + key : key; newObj.set(newKey, renameNumericKeys(value)); }); return newObj; } else if (node.isArray()) { node.elements().forEachRemaining(JsonNumericKeyHandler::renameNumericKeys); } return node; } }
使用时先将JSON字符串转为JsonNode,调用该方法处理后再交给dom4j。
3. 启用dom4j非严格模式
通过系统属性关闭dom4j的严格校验,使其行为与1.5.2版本对齐:
- 启动JVM时添加参数:
-Ddom4j.strict=false - 或在代码中动态设置:
System.setProperty("dom4j.strict", "false");
注意:这是全局设置,可能会导致其他XML处理场景违反W3C规范,需谨慎使用。
方案选择建议
- 若需要完全兼容旧版本行为,优先选择方案1或方案3;
- 若业务允许临时修改键名,方案2更稳妥,不会影响XML规范符合性。
内容的提问来源于stack exchange,提问作者ashok
相关产品推荐
相关产品推荐

