Java中如何对JSON数组元素按指定嵌套字段值进行排序?
自定义JsonNodeFactory不生效原因
你自定义的JsonNodeFactory没有触发,是因为mapper.writeValueAsString(Object obj)直接序列化Java对象的流程中,默认不会构造中间的JsonNode树结构,仅在显式调用mapper.readTree()、mapper.createObjectNode()等操作JsonNode的方法时才会调用该工厂的创建逻辑。
另外你之前配置的ORDER_MAP_ENTRIES_BY_KEYS、SORT_PROPERTIES_ALPHABETICALLY仅用于控制JSON对象的键排序,不涉及数组元素的排序逻辑,数组排序需要单独实现。
实现方案
方案1:序列化前直接排序原始集合(性能最优、实现最简单)
如果你持有要序列化的原始Java对象,直接对数组对应的List字段按规则排序后再序列化即可:
// 示例:按firstName.value升序排序 response.getTestArray().sort(Comparator.comparing(user -> user.getFirstName().getValue())); String sortedJson = mapper.writeValueAsString(response);
方案2:通过JsonNode中转实现通用排序
如果你需要通用处理任意JSON结构、或没有原始Java对象只有JSON字符串,可以先将内容转为JsonNode,递归遍历所有数组节点排序后再序列化:
// 通用数组排序工具方法 public static void sortArrayNodes(JsonNode node, Comparator<JsonNode> elementComparator) { if (node.isArray()) { ArrayNode arrayNode = (ArrayNode) node; List<JsonNode> elements = new ArrayList<>(); arrayNode.forEach(elements::add); elements.sort(elementComparator); arrayNode.removeAll(); elements.forEach(arrayNode::add); } else if (node.isObject()) { node.fields().forEachRemaining(entry -> sortArrayNodes(entry.getValue(), elementComparator)); } }
使用方式:
// 1. 转为JsonNode JsonNode rootNode = mapper.valueToTree(someObject); // 2. 定义排序规则,示例按firstName.value升序 Comparator<JsonNode> comparator = (o1, o2) -> { String v1 = o1.path("firstName").path("value").asText(""); String v2 = o2.path("firstName").path("value").asText(""); return v1.compareTo(v2); }; // 3. 执行排序 sortArrayNodes(rootNode, comparator); // 4. 序列化输出 String sortedJson = mapper.writeValueAsString(rootNode);
方案3:自定义序列化器全局生效
如果你希望对指定类型的List全局自动排序,可以注册自定义序列化器到ObjectMapper:
// 自定义序列化器 public class SortedUserListSerializer extends StdSerializer<List<User>> { private static final Comparator<User> COMPARATOR = Comparator.comparing(user -> user.getFirstName().getValue()); public SortedUserListSerializer() { super(TypeFactory.defaultInstance().constructParametricType(List.class, User.class)); } @Override public void serialize(List<User> value, JsonGenerator gen, SerializerProvider provider) throws IOException { List<User> sortedList = value.stream().sorted(COMPARATOR).collect(Collectors.toList()); provider.defaultSerializeValue(sortedList, gen); } }
注册到ObjectMapper:
SimpleModule module = new SimpleModule(); module.addSerializer(new SortedUserListSerializer()); mapper.registerModule(module);
之后所有List<User>类型的字段序列化时都会自动按规则排序。
内容的提问来源于stack exchange,提问作者Bestows In Constructing
相关产品推荐
相关产品推荐

