【问题标题】:How to sort json array elements in java如何在java中对json数组元素进行排序
【发布时间】:2021-11-25 18:11:36
【问题描述】:

我知道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 进行排序?

【问题讨论】:

  • 是否可以选择将 json 内容传输到纯 java 对象中进行排序?有时不存在直接的方式吗?
  • stackoverflow.com/users/326807/reporter 我想我可以将它移动到一个对象,但是如果我有一个有很多嵌套的 json,那么对所有内部 json 数组进行排序并将它们转换为对象并定义它似乎很脏他们每个人的比较器。尽管如此,我还是不明白为什么在代码中没有使用 JsonNodeFactory ...如果工厂中只出现线程我想它可以解决我的问题

标签: java json fasterxml


【解决方案1】:

这里有一个解决方案

我需要打电话给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);
    }
}

【讨论】:

  • 如果对象不是isObjectisArray,则它是isPojo, isNumber isIntegralNumber isFloatingPointNumber isShort isInt isLong @9 987654335@isBigDecimalisBigIntegerisTextualisBooleanisNullisBinary,我们可以通过asText方法来比较它们。所有这些,除了isPojo。我实际上不知道如何比较这样的节点。如果你知道,在这里写下你的解决方案,我会更新代码。
  • “可配置”?通过什么方式?通过为每种类型的元素指定比较器?那不是答案。您的代码不适用于结构未知的元素,但适用于已知结构的元素。我没有忽略你的回答。我问你一个问题。
  • 一个正常人在这种情况下,如果他知道自己是对的,就一步一步地证明自己的情况,特别是对自己的一言一行负责。如果你删除你的话,那么你根本无法回答他们。一个负责任的人对每一个字负责,包括错误的,只有在错误的情况下,他才承认这是错误的。你只是删除你的话,所以你不能回答他们。我不知道你几岁,但要么回答你写的东西,要么再见。
  • 烟消云散,烟消云散
猜你喜欢
  • 2015-06-28
  • 1970-01-01
  • 1970-01-01
  • 2019-06-06
  • 2020-01-07
  • 2011-01-08
  • 1970-01-01
  • 2016-10-11
  • 2013-06-08
相关资源
最近更新 更多