Java按指定section替换JSON变量后反序列化为POJO的注解实现咨询
结论
无法仅通过Java JSON库的常规基础注解直接实现该需求,你需要结合自定义反序列化逻辑完成,以业界最常用的Jackson库为例,可以通过「自定义反序列化器+注解」的形式实现你要的效果,具体思路如下:
实现方案
- 第一步:先定义原始JSON对应的基础POJO结构,包含common、section1、section2三个节点的对应字段,也可以用
Map<String, Section>类型存储所有业务分段,方便后续扩展更多section。 - 第二步:自定义反序列化注解,比如命名为
@SectionAware,用于标注需要输出最终合并后data结果的字段,同时支持传入section参数。 - 第三步:实现对应自定义反序列化器,核心逻辑如下:
- 读取完整JSON树,根据传入的section参数获取对应分段的
variables变量映射表、以及data字段存储的ref列表 - 提取common块下的所有data条目,筛选出ref值在上述ref列表中的条目
- 遍历筛选后条目的所有字段值,匹配
${变量名}格式的占位符,从variables映射表中取出对应实际值完成替换,移除不需要的ref字段后即可得到你要的最终data结构
- 读取完整JSON树,根据传入的section参数获取对应分段的
- 如果业务规则后续可能频繁调整,更推荐你先把JSON直接反序列化为原始结构POJO,单独写一个工具类做占位符替换、字段合并的逻辑,这种方式可读性和可维护性比自定义反序列化器更高。
核心代码示例
// 自定义注解 @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonDeserialize(using = SectionDataDeserializer.class) public @interface SectionAware { String section() default ""; } // 自定义反序列化器核心逻辑 public class SectionDataDeserializer extends StdDeserializer<List<Map<String, Object>>> { @Override public List<Map<String, Object>> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode root = p.readValueAsTree(); // 可通过注解属性、ThreadLocal或者Jackson的注入机制获取传入的section参数 String section = ctxt.findInjectableValue("targetSection", null, null).toString(); JsonNode sectionNode = root.get(section); // 读取变量映射表 Map<String, String> variables = ctxt.readValue(sectionNode.get("variables").traverse(p.getCodec()), new TypeReference<Map<String, String>>() {}); // 读取需要引用的ref列表 List<String> refList = ctxt.readValue(sectionNode.get("data").traverse(p.getCodec()), new TypeReference<List<String>>() {}); // 处理common数据并替换占位符 List<Map<String, Object>> result = new ArrayList<>(); for (JsonNode commonDataItem : root.get("common").get("data")) { String ref = commonDataItem.get("ref").asText(); if (!refList.contains(ref)) continue; Map<String, Object> item = ctxt.readValue(commonDataItem.traverse(p.getCodec()), new TypeReference<Map<String, Object>>() {}); item.remove("ref"); // 占位符替换逻辑 item.replaceAll((key, value) -> { String valStr = value.toString(); if (valStr.startsWith("${") && valStr.endsWith("}")) { return variables.getOrDefault(valStr, valStr); } return value; }); result.add(item); } return result; } }
内容的提问来源于stack exchange,提问作者tg_anon
相关产品推荐
相关产品推荐

