使用Jackson如何根据JSON的column值动态查找POJO对应的getter方法
实现方案
方案1:预定义字段与Getter的映射(推荐,性能高、类型安全)
直接把所有字段对应的getter方法提前存在Map里,运行时直接拿对应的取值函数,不需要反射,没有额外性能损耗,也不会有反射的异常问题。
首先定义静态映射:
import java.util.function.Function; import java.util.function.BiPredicate; // 先定义静态的字段Getter映射,Java8环境可以换成HashMap逐个put初始化 private static final Map<String, Function<CustomerPojo, String>> FIELD_GETTER_MAP = Map.of( "name", CustomerPojo::getName, "address", CustomerPojo::getAddress, "city", CustomerPojo::getCity, "country", CustomerPojo::getCountry, // 年龄字段转字符串适配比较逻辑 "age", pojo -> String.valueOf(pojo.getAge()) ); // 还可以顺便把操作符也预定义成断言,省去switch判断 private static final Map<String, BiPredicate<String, String>> OPERATOR_PREDICATE_MAP = Map.of( "CONTAINS", (fieldVal, targetVal) -> fieldVal != null && fieldVal.contains(targetVal), "NOT CONTAINS", (fieldVal, targetVal) -> fieldVal == null || !fieldVal.contains(targetVal), "EQUAL", Objects::equals, "NOT EQUAL", (fieldVal, targetVal) -> !Objects.equals(fieldVal, targetVal) );
改造后的业务方法如下,同时修复了原方法中多条件共享集合变量的逻辑问题:
private List<CustomerPojo> groupOperatorAND(List<JsonNode> conditions, List<CustomerPojo> list) { List<CustomerPojo> result = new ArrayList<>(list); // 遍历所有条件依次过滤 for (JsonNode condNode : conditions) { String column = condNode.get("column").asText(); String operator = condNode.get("Operator").asText(); String value = condNode.get("Value").asText(); // 拿到对应字段的取值函数 Function<CustomerPojo, String> getter = FIELD_GETTER_MAP.get(column); if (getter == null) { throw new IllegalArgumentException("不支持的字段:" + column); } // 拿到对应操作符的断言 BiPredicate<String, String> predicate = OPERATOR_PREDICATE_MAP.get(operator); if (predicate == null) { throw new IllegalArgumentException("不支持的操作符:" + operator); } // 过滤集合 result = result.stream() .filter(pojo -> predicate.test(getter.apply(pojo), value)) .collect(Collectors.toList()); // 无匹配项时提前退出 if (result.isEmpty()) { break; } } return result; }
调用时直接把JSON中的condition数组作为参数传入即可,逻辑比原实现更清晰。
方案2:反射实现(不需要手动维护映射,性能稍差)
如果你的POJO字段经常变动,不想手动维护映射关系,可以用反射动态调用getter方法,注意处理异常即可:
private Object getFieldValue(CustomerPojo pojo, String column) throws Exception { // 按JavaBean规范拼接getter方法名:首字母大写+前缀get String getterName = "get" + column.substring(0, 1).toUpperCase() + column.substring(1); Method method = CustomerPojo.class.getMethod(getterName); return method.invoke(pojo); }
在过滤逻辑中调用该方法即可:
// filter中使用示例 .filter(li -> { try { String fieldVal = String.valueOf(getFieldValue(li, column)); if ("CONTAINS".equals(operator)) { return fieldVal.contains(value); } // 其他操作符判断逻辑 } catch (Exception e) { throw new RuntimeException("获取字段值失败", e); } })
注意:反射方案需要处理方法不存在、访问权限、调用异常等问题,性能比预定义映射方案差,仅适合字段频繁变动的场景。
内容的提问来源于stack exchange,提问作者Shivanand Bhangari
相关产品推荐
相关产品推荐

