不使用注解能否指定Jackson中ObjectNode属性的序列化顺序?
不使用注解实现Jackson ObjectNode自定义序列化顺序
当然可以,下面提供两种实用方案,无需依赖注解就能精准控制ObjectNode的属性序列化顺序:
方案1:通过自定义BeanSerializerModifier全局配置
这种方法适合需要全局统一序列化顺序的场景,一次配置后所有ObjectNode的序列化都会遵循指定规则:
ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule() { @Override public void setupModule(SetupContext context) { context.addBeanSerializerModifier(new BeanSerializerModifier() { @Override public JsonSerializer<?> modifyObjectSerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) { // 仅对ObjectNode类型生效 if (ObjectNode.class.isAssignableFrom(beanDesc.getBeanClass())) { List<String> desiredOrder = Arrays.asList("b", "a", "c"); // 这里定义你的自定义顺序 if (serializer instanceof BeanSerializer) { BeanSerializer beanSerializer = (BeanSerializer) serializer; List<BeanPropertyWriter> propertyWriters = new ArrayList<>(beanSerializer.getPropertyWriters()); // 按自定义顺序排序属性写入器 propertyWriters.sort((w1, w2) -> { int idx1 = desiredOrder.indexOf(w1.getName()); int idx2 = desiredOrder.indexOf(w2.getName()); // 不在指定列表的属性默认放在最后,保持原有相对顺序 if (idx1 == -1 && idx2 == -1) return 0; if (idx1 == -1) return 1; if (idx2 == -1) return -1; return Integer.compare(idx1, idx2); }); return beanSerializer.withProperties(propertyWriters); } } return serializer; } }); } }); // 测试代码 ObjectNode node = mapper.createObjectNode(); node.put("a", 1); node.put("b", 2); node.put("c", 3); String json = mapper.writeValueAsString(node); // 输出结果:{"b":2,"a":1,"c":3}
方案2:手动使用JsonGenerator按顺序写入(局部场景)
如果只是针对单个ObjectNode需要自定义顺序,直接用JsonGenerator按指定顺序写入属性更直接,避免全局配置的影响:
ObjectMapper mapper = new ObjectMapper(); ObjectNode node = mapper.createObjectNode(); node.put("a", 1); node.put("b", 2); node.put("c", 3); StringWriter sw = new StringWriter(); try (JsonGenerator generator = mapper.getFactory().createGenerator(sw)) { generator.writeStartObject(); // 严格按照你需要的顺序写入每个属性 generator.writeNumberField("b", node.get("b").asInt()); generator.writeNumberField("a", node.get("a").asInt()); generator.writeNumberField("c", node.get("c").asInt()); generator.writeEndObject(); } catch (IOException e) { e.printStackTrace(); } String json = sw.toString(); // 输出结果:{"b":2,"a":1,"c":3}
方案对比
- 方案1适合全局统一规则,无需重复编写代码;
- 方案2适合临时、局部的自定义顺序,灵活性更高,但需要手动处理每个属性的写入。
内容的提问来源于stack exchange,提问作者Gili
相关产品推荐
相关产品推荐

