JAXB自定义HashMap<String,Object>编组:如何去除type/value嵌套?
解决MOXy序列化Map<String, Object>时的type/value嵌套问题
你遇到的这个type/value嵌套问题,本质是MOXy默认会对Object类型的属性生成类型信息包装——因为它无法确定值的具体类型,所以用type字段标记类型、value字段存实际值。但你的HashMap里明确存储的是Boolean、Long、String这三种具体类型,我们可以通过以下几种方式解决:
方案1:修改自定义HashMapAdapter,直接输出原始值
你的HashMapAdapter目前应该是在marshal阶段把每个Object值包装成了带type和value的结构,我们可以调整它的逻辑,针对已知类型直接返回原始值:
import javax.xml.bind.annotation.adapters.XmlAdapter; import java.util.HashMap; import java.util.Map; public class HashMapAdapter extends XmlAdapter<Map<String, Object>, Map<String, Object>> { @Override public Map<String, Object> unmarshal(Map<String, Object> inputMap) throws Exception { // 保留原有的反序列化逻辑不变 return inputMap; } @Override public Map<String, Object> marshal(Map<String, Object> sourceMap) throws Exception { Map<String, Object> resultMap = new HashMap<>(); for (Map.Entry<String, Object> entry : sourceMap.entrySet()) { Object value = entry.getValue(); // 针对你存储的三种类型,直接放入原始值 if (value instanceof Boolean || value instanceof Long || value instanceof String) { resultMap.put(entry.getKey(), value); } else { // 若有其他类型,可在这里自定义处理,或保留默认包装逻辑 resultMap.put(entry.getKey(), value); } } return resultMap; } }
修改后,适配器会直接把Boolean、Long、String类型的值序列化,不会生成嵌套结构。
方案2:用MOXy原生注解替代适配器
如果你不想维护自定义适配器,可以直接利用MOXy的@XmlVariableNode注解,它专门用来处理Map的key作为JSON节点名、value作为节点值的场景:
步骤1:给实体类添加注解
import org.eclipse.persistence.oxm.annotations.XmlVariableNode; public class YourEntity { // 用key作为JSON的节点名 @XmlVariableNode("key") private Map<String, Object> data; // 别忘了添加getter和setter方法 public Map<String, Object> getData() { return data; } public void setData(Map<String, Object> data) { this.data = data; } }
步骤2:配置MOXy为JAXB提供者
在实体类所在的包下创建jaxb.properties文件,内容如下:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
这样MOXy会直接按照你期望的格式序列化Map,不会生成type/value嵌套。
方案3:禁用MOXy的默认类型信息输出
如果上述方法不生效,可能是MOXy默认启用了类型信息输出,你可以通过注解强制禁用:
import org.eclipse.persistence.oxm.annotations.XmlMarshallerProperties; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; public class YourEntity { @XmlJavaTypeAdapter(HashMapAdapter.class) @XmlMarshallerProperties( jsonTypeInfo = XmlMarshallerProperties.JSON_TYPE_INFO_NEVER ) private Map<String, Object> data; // getter和setter方法 }
JSON_TYPE_INFO_NEVER会告诉MOXy不要为Object类型的值输出类型信息,直接序列化原始值。
最后,确认Payara Micro环境:默认情况下Payara Micro使用MOXy作为JAXB提供者,但如果你的项目依赖了其他JAXB实现(比如JDK自带的),记得排除这些依赖,避免冲突。
内容的提问来源于stack exchange,提问作者sbaeurle
相关产品推荐
相关产品推荐

