基于EclipseLink MOXy转换Employee XML版本报错求助
问题解答:基于EclipseLink MOXy实现不同版本Employee XML的转换
转换需求是否可实现?
当然可以实现!你的场景是将管理员版(v1)的Employee结构转换为普通用户版(v2)的结构,本质是从字段更全的模型映射到子集模型,MOXy完全支持这类场景,不管是直接对象拷贝还是动态JAXB方案都能搞定。
你的代码存在的核心问题
你当前的代码逻辑完全绕反了,而且对DynamicEntity的用法存在明显误解:
- 错误的转换流程:你把v2的POJO转成XML,再用v1的
DynamicJAXBContext反序列化得到DynamicEntity,这相当于把v2结构强行塞进v1的模型里,完全违背了"从v1转v2"的核心需求。 - 误用
JAXB.unmarshal():JAXB.unmarshal()的作用是从**XML源(流/文件等)**反序列化成对象,但你传入的dynamicEntity.get("Head")已经是一个DynamicEntityImpl实例,不是XML源,这直接触发了ClassCastException。
修正方案(两种可选思路)
思路一:直接对象拷贝(最适合结构差异小的场景)
因为v2是v1的子集,直接从v1的实体类中提取需要的字段,赋值给v2的实体类即可,不需要用到DynamicJAXB:
// 假设你已经接收到v1版本的Employee实例(管理员版) com.something.v1.Employee adminEmployee = ...; // 创建v2版本的Employee实例(普通用户版) com.something.v2.Employee workerEmployee = new com.something.v2.Employee(); // 处理Head节点:只保留id和设置type为WORKER com.something.v2.Head workerHead = new com.something.v2.Head(); workerHead.setId(adminEmployee.getHead().getId()); workerHead.setType("WORKER"); // 如果是枚举类型,直接用枚举值比如WorkerType.WORKER workerEmployee.setHead(workerHead); // 处理Address节点:只保留type和文本内容,忽略from属性 com.something.v2.Address workerAddress = new com.something.v2.Address(); workerAddress.setType(adminEmployee.getAddress().getType()); workerAddress.setValue(adminEmployee.getAddress().getValue()); // 假设Address的文本内容存在value字段中 workerEmployee.setAddress(workerAddress); // 之后可以直接把workerEmployee序列化成v2格式的XML
思路二:用MOXy DynamicJAXBContext动态生成v2结构(适合结构差异大的场景)
如果未来两个版本的结构差异变大,直接拷贝会很繁琐,可以用DynamicJAXBContext基于v2的XSD动态创建实体,再从v1对象中填充数据:
// 加载v2版本的XSD,创建DynamicJAXBContext DynamicJAXBContext v2DynamicContext = DynamicJAXBContextFactory.createContextFromXSD( Thread.currentThread().getContextClassLoader().getResourceAsStream("Employee-v2.xsd"), null, com.something.v2.Employee.class.getClassLoader(), null ); // 创建v2版本的DynamicEntity实例 DynamicEntity workerEmpEntity = v2DynamicContext.newDynamicEntity("com.something.v2.Employee"); // 从v1的管理员版对象中提取数据填充 com.something.v1.Employee adminEmployee = ...; // 填充Head节点 DynamicEntity workerHeadEntity = v2DynamicContext.newDynamicEntity("com.something.v2.Head"); workerHeadEntity.set("id", adminEmployee.getHead().getId()); workerHeadEntity.set("type", "WORKER"); workerEmpEntity.set("Head", workerHeadEntity); // 填充Address节点 DynamicEntity workerAddrEntity = v2DynamicContext.newDynamicEntity("com.something.v2.Address"); workerAddrEntity.set("type", adminEmployee.getAddress().getType()); workerAddrEntity.set("value", adminEmployee.getAddress().getValue()); // 对应XML中的文本内容 workerEmpEntity.set("Address", workerAddrEntity); // 将DynamicEntity序列化成v2格式的XML StringWriter writer = new StringWriter(); v2DynamicContext.createMarshaller().marshal(workerEmpEntity, writer); String v2XmlOutput = writer.toString();
内容的提问来源于stack exchange,提问作者Abhinab Kanrar
相关产品推荐
相关产品推荐

