如何对 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);
}
}
我知道在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);
}
}