如何对 java 中的 json 数组元素进行排序

How to sort json array elements in java

我知道在json

中有一种排序地图的方法

    mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
    mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);

来自 fasterxml

但是当我得到这样一个数组时:

{
  "testArray": [
    {
      "firstName": {
        "value": "Lui"
      },
      "lastName": {
        "value": "Armstrong"
      },
      "photo": "234"
    }, {
      "firstName": {
        "value": "Charley"
      },
      "lastName": {
        "value": "Mor"
      },
      "photo": "123"
    }
  ]
}

如果字段键相等,我想先按等于字段值排序。所以我需要示例中的第一个元素在最后一个元素之后,因为单词 Charley 必须在 Lui 之前,并且它们都有相同的路径 - firstName.value。键的顺序相同,原因是ORDER_MAP_ENTRIES_BY_KEYS。因此,如果路径相同,我希望元素的顺序必须基于值,但它不会发生。

我尝试使用

ObjectMapper mapper = new ObjectMapper();
mapper.setNodeFactory(new JsonNodeFactory() {
    @Override
    public ObjectNode objectNode() {
        return new ObjectNode(this, new TreeMap<String, JsonNode>());
    }

    @Override
    public ArrayNode arrayNode() {
        return new ArrayNode(this, new SomeSortedArrayListThatBaseOnComparatorInComstructor<JsonNode>(new Comparator<JsonNode>() {
            @Override
            public int compare(final JsonNode o1, final JsonNode o2) {
                return //logic to compare
            }
        }) { });

但是当我打电话时

mapper.writeValueAsString(someObject)

代码不使用我的JsonNodeFactory。在调试中没有线程出现在方法 objectNode()arrayNode().

我不明白为什么。

或者也许还有另一种方法可以对这样的 json 进行排序?

添加一些搜索结果以便更好地google搜索: How to sort array of json objects in java, How can I sort a JSONArray of objects in JAVA, How to sort json objects using the order of another json sort json array elements java

这是一个解决方案

我需要调用 readTree,使用 JsonNodeFactory

然后通过writeValueAsString

转换成字符串

这里是代码

public static String writeAsSortedJson(Object object) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setNodeFactory(getArrayNodeKeyValueSortingNodeFactory());

    mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
    mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);

    String preparedJson = mapper.writeValueAsString(object);
    JsonNode jsonNode = mapper.readTree(preparedJson);

    return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
}

@SuppressWarnings("JavaNCSS")
public static JsonNodeFactory getArrayNodeKeyValueSortingNodeFactory() {
    return new JsonNodeFactory() {
        @Override
        public ObjectNode objectNode() {
            return new ObjectNode(this, new TreeMap<String, JsonNode>());
        }

        @SuppressWarnings("JavaNCSS")
        @Override
        public ArrayNode arrayNode() {
            return new ArrayNode(this, new SortedArrayList<JsonNode>(new Comparator<JsonNode>() {
                @Override
                public int compare(final JsonNode o1, final JsonNode o2) {
                    return compareRecursively(o1, o2);
                }

                private int compareRecursively(final JsonNode o1, final JsonNode o2) {
                    if (o1.isObject() && o2.isObject()) {
                        return compareObjectNodes(o1, o2);
                    } else if (o1.isObject()) {
                        return 1;
                    } else if (o2.isObject()) {
                        return -1;
                    } else if (o1.isArray() && o2.isArray()) {
                        return compareArrayNodes(o1, o2);
                    } else if (o1.isArray()) {
                        return 1;
                    } else if (o2.isArray()) {
                        return -1;
                    }
                    return o1.asText().compareTo(o2.asText());
                }

                private int compareArrayNodes(final JsonNode o1, final JsonNode o2) {
                    List<JsonNode> elements1 = Lists.newArrayList(o1.elements());
                    List<JsonNode> elements2 = Lists.newArrayList(o2.elements());

                    for (int i = 0; i < elements1.size() || i < elements2.size(); i++) {
                        if (i >= elements1.size()) {
                            return -1;
                        } else if (i >= elements2.size()) {
                            return 1;
                        }

                        JsonNode jsonNode1 = elements1.get(i);
                        JsonNode jsonNode2 = elements2.get(i);
                        int compareRecursively = compareRecursively(jsonNode1, jsonNode2);
                        if (compareRecursively != 0) {
                            return compareRecursively;
                        }
                    }

                    return 0;
                }

                @SuppressWarnings("ReturnCountExtended")
                private int compareObjectNodes(JsonNode o1, JsonNode o2) {
                    List<Map.Entry<String, JsonNode>> elements1 = Lists.newArrayList(o1.fields());
                    List<Map.Entry<String, JsonNode>> elements2 = Lists.newArrayList(o2.fields());
                    if (elements1.isEmpty() && elements2.isEmpty()) {
                        return 0;
                    } else if (elements1.isEmpty()) {
                        return -1;
                    } else if (elements2.isEmpty()) {
                        return 1;
                    }

                    for (int i = 0; i < elements1.size() || i < elements2.size(); i++) {
                        if (i >= elements1.size()) {
                            return -1;
                        } else if (i >= elements2.size()) {
                            return 1;
                        }

                        Map.Entry<String, JsonNode> entry1 = elements1.get(i);
                        Map.Entry<String, JsonNode> entry2 = elements2.get(i);
                        int compare = entry1.getKey().compareTo(entry2.getKey());
                        if (compare == 0) {
                            int compareRecursively = compareRecursively(entry1.getValue(), entry2.getValue());
                            if (compareRecursively != 0) {
                                return compareRecursively;
                            }
                        } else {
                            return compare;
                        }
                    }

                    return 0;
                }
            }) { });
        }
    };
}

public static class SortedArrayList<T> implements List<T> {
    private final List<T> delegate = new ArrayList<>();
    private final Comparator<T> comparator;

    public SortedArrayList(Comparator<T> comparator) {
        this.comparator = comparator;
    }

    @Override
    public int size() {
        return delegate.size();
    }

    @Override
    public boolean isEmpty() {
        return delegate.isEmpty();
    }

    @Override
    public boolean contains(final Object o) {
        return delegate.contains(o);
    }

    @NotNull
    @Override
    public Iterator<T> iterator() {
        return delegate.iterator();
    }

    @NotNull
    @Override
    public Object[] toArray() {
        return delegate.toArray();
    }

    @NotNull
    @Override
    public <T1> T1[] toArray(@NotNull final T1[] a) {
        return delegate.toArray(a);
    }

    @Override
    public boolean add(final T t) {
        boolean add = delegate.add(t);
        sort();
        return add;
    }

    @Override
    public void add(final int index, final T element) {
        delegate.add(index, element);
        sort();
    }

    @Override
    public boolean remove(final Object o) {
        boolean remove = delegate.remove(o);
        sort();
        return remove;
    }

    @Override
    public T remove(final int index) {
        T remove = delegate.remove(index);
        sort();
        return remove;
    }

    @Override
    public boolean containsAll(@NotNull final Collection<?> c) {
        return delegate.containsAll(c);
    }

    @Override
    public boolean addAll(@NotNull final Collection<? extends T> c) {
        boolean addAll = delegate.addAll(c);
        sort();
        return addAll;
    }

    @Override
    public boolean addAll(int index, @NotNull Collection<? extends T> c) {
        boolean addAll = delegate.addAll(index, c);
        sort();
        return addAll;
    }

    @Override
    public boolean removeAll(@NotNull final Collection<?> c) {
        boolean removeAll = delegate.removeAll(c);
        sort();
        return removeAll;
    }

    @Override
    public boolean retainAll(@NotNull final Collection<?> c) {
        boolean retainAll = delegate.retainAll(c);
        sort();
        return retainAll;
    }

    @Override
    public void clear() {
        delegate.clear();
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        SortedArrayList<?> that = (SortedArrayList<?>) o;
        return Objects.equals(delegate, that.delegate);
    }

    @Override
    public int hashCode() {
        return Objects.hash(delegate);
    }

    @Override
    public T get(final int index) {
        return delegate.get(index);
    }

    @Override
    public T set(final int index, final T element) {
        delegate.set(index, element);
        sort();
        return element;
    }

    @Override
    public int indexOf(final Object o) {
        return delegate.indexOf(o);
    }

    @Override
    public int lastIndexOf(final Object o) {
        return delegate.lastIndexOf(o);
    }

    @NotNull
    @Override
    public ListIterator<T> listIterator() {
        return delegate.listIterator();
    }

    @NotNull
    @Override
    public ListIterator<T> listIterator(final int index) {
        return delegate.listIterator(index);
    }

    @NotNull
    @Override
    public List<T> subList(final int fromIndex, final int toIndex) {
        return delegate.subList(fromIndex, toIndex);
    }

    private void sort() {
        delegate.sort(comparator);
    }
}