Jackson ACCEPT_SINGLE_VALUE_AS_ARRAY与PolymorphicTypeValidator搭配失效 反序列化JPMML DefineFunction异常
解决方案
你的问题本质是两个不匹配:1. 入参JSON结构和JPMML模型的字段定义不匹配(Expression子类直接暴露在DefineFunction层级,没有被Expression字段包裹);2. 多余的全局多态配置覆盖了模型自带的多态注解,引发List反序列化冲突。不需要修改JPMML源码,也不需要写全量自定义反序列化器,按以下步骤处理即可:
步骤1:预处理JSON结构,补全Expression包裹层
因为JPMML的DefineFunction中表达式字段被定义为Expression,且多态配置为包装对象模式,需要把入参中直接放在DefineFunction下的表达式子类(比如示例中的MapValues)移动到Expression字段下:
// 先读取原始输入为JsonNode ObjectMapper rawMapper = new ObjectMapper(); JsonNode rootNode = rawMapper.readTree(originalInputStr); ObjectNode defineFunctionNode = (ObjectNode) rootNode; // 所有Expression子类的名称列表,对应@JsonSubTypes里的name值 Set<String> expressionSubTypeNames = Set.of("Constant", "FieldRef", "NormContinuous", "NormDiscrete", "Discretize", "MapValues", "TextIndex", "Apply", "Aggregate", "Lag"); // 查找属于Expression子类的字段 for (String fieldName : (Iterable<String>) defineFunctionNode::fieldNames) { if (expressionSubTypeNames.contains(fieldName)) { // 新建Expression包装节点 ObjectNode expressionNode = rawMapper.createObjectNode(); expressionNode.set(fieldName, defineFunctionNode.get(fieldName)); defineFunctionNode.set("Expression", expressionNode); // 删除原有的子类字段 defineFunctionNode.remove(fieldName); break; } }
步骤2:配置ObjectMapper反序列化
只开单值转数组配置即可,不需要开启全局多态(JPMML模型的Expression字段已自带多态注解,全局多态会冲突):
ObjectMapper mapper = new ObjectMapper() .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); DefineFunction defineFunction = mapper.convertValue(defineFunctionNode, DefineFunction.class);
可选优化
如果需要处理大量同类结构,可以把上述JSON预处理逻辑封装为一个BeanDeserializerModifier,注册到ObjectMapper中,不需要每次手动处理节点,完全自动化处理所有符合JPMML结构的反序列化场景。
内容的提问来源于stack exchange,提问作者jiraspav
相关产品推荐
相关产品推荐

