Skip to content

Commit b76664e

Browse files
committed
Support arrays, collections, & maps in ObjectUtils.nullSafeConciseToString()
Prior to this commit, there was no explicit support for arrays, collections, and maps in nullSafeConciseToString(). This lead to string representations such as the following, regardless of whether the array, collection, or map was empty. - char[]@1623b78d - java.util.ImmutableCollections$List12@74fe5c40 - java.util.ImmutableCollections$MapN@10e31a9a This commit introduces explicit support for arrays, collections, and maps in nullSafeConciseToString(), which results in the following empty/non-empty string representations. - array: {} / {...} - collection: [] / [...] - map: {} / {...} The reason a string representation of an array uses "{}" instead of "[]" (like in Arrays.toString(...)) is that ObjectUtils.nullSafeToString(<array>) already follows that convention, and the implementation of nullSafeConciseToString() aligns with that for the sake of consistency. Closes gh-30810
1 parent ae13823 commit b76664e

File tree

2 files changed

+50
-10
lines changed

2 files changed

+50
-10
lines changed

spring-core/src/main/java/org/springframework/util/ObjectUtils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public abstract class ObjectUtils {
6969
private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;
7070
private static final String ARRAY_ELEMENT_SEPARATOR = ", ";
7171
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
72+
private static final String NON_EMPTY_ARRAY = ARRAY_START + "..." + ARRAY_END;
73+
private static final String EMPTY_COLLECTION = "[]";
74+
private static final String NON_EMPTY_COLLECTION = "[...]";
7275

7376

7477
/**
@@ -943,6 +946,16 @@ public static String nullSafeConciseToString(@Nullable Object obj) {
943946
return (optional.isEmpty() ? "Optional.empty" :
944947
"Optional[%s]".formatted(nullSafeConciseToString(optional.get())));
945948
}
949+
if (obj.getClass().isArray()) {
950+
return (Array.getLength(obj) == 0 ? EMPTY_ARRAY : NON_EMPTY_ARRAY);
951+
}
952+
if (obj instanceof Collection<?> collection) {
953+
return (collection.isEmpty() ? EMPTY_COLLECTION : NON_EMPTY_COLLECTION);
954+
}
955+
if (obj instanceof Map<?, ?> map) {
956+
// EMPTY_ARRAY and NON_EMPTY_ARRAY are also used for maps.
957+
return (map.isEmpty() ? EMPTY_ARRAY : NON_EMPTY_ARRAY);
958+
}
946959
if (obj instanceof Class<?> clazz) {
947960
return clazz.getName();
948961
}

spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import java.sql.SQLException;
3131
import java.time.LocalDate;
3232
import java.time.ZoneId;
33-
import java.util.ArrayList;
3433
import java.util.Collections;
3534
import java.util.Currency;
3635
import java.util.Date;
@@ -1034,19 +1033,47 @@ void nullSafeConciseToStringForZoneId() {
10341033
}
10351034

10361035
@Test
1037-
void nullSafeConciseToStringForArraysAndCollections() {
1038-
List<String> list = List.of("a", "b", "c");
1039-
assertThat(ObjectUtils.nullSafeConciseToString(new int[][] {{1, 2}, {3, 4}})).startsWith(prefix(int[][].class));
1040-
assertThat(ObjectUtils.nullSafeConciseToString(list.toArray())).startsWith(prefix(Object[].class));
1041-
assertThat(ObjectUtils.nullSafeConciseToString(list.toArray(String[]::new))).startsWith(prefix(String[].class));
1042-
assertThat(ObjectUtils.nullSafeConciseToString(new ArrayList<>(list))).startsWith(prefix(ArrayList.class));
1043-
assertThat(ObjectUtils.nullSafeConciseToString(new HashSet<>(list))).startsWith(prefix(HashSet.class));
1036+
void nullSafeConciseToStringForEmptyArrays() {
1037+
assertThat(ObjectUtils.nullSafeConciseToString(new char[] {})).isEqualTo("{}");
1038+
assertThat(ObjectUtils.nullSafeConciseToString(new int[][] {})).isEqualTo("{}");
1039+
assertThat(ObjectUtils.nullSafeConciseToString(new String[] {})).isEqualTo("{}");
1040+
assertThat(ObjectUtils.nullSafeConciseToString(new Integer[][] {})).isEqualTo("{}");
10441041
}
10451042

10461043
@Test
1047-
void nullSafeConciseToStringForMaps() {
1044+
void nullSafeConciseToStringForNonEmptyArrays() {
1045+
assertThat(ObjectUtils.nullSafeConciseToString(new char[] {'a'})).isEqualTo("{...}");
1046+
assertThat(ObjectUtils.nullSafeConciseToString(new int[][] {{1}, {2}})).isEqualTo("{...}");
1047+
assertThat(ObjectUtils.nullSafeConciseToString(new String[] {"enigma"})).isEqualTo("{...}");
1048+
assertThat(ObjectUtils.nullSafeConciseToString(new Integer[][] {{1}, {2}})).isEqualTo("{...}");
1049+
}
1050+
1051+
@Test
1052+
void nullSafeConciseToStringForEmptyCollections() {
1053+
List<String> list = List.of();
1054+
Set<Integer> set = Set.of();
1055+
assertThat(ObjectUtils.nullSafeConciseToString(list)).isEqualTo("[]");
1056+
assertThat(ObjectUtils.nullSafeConciseToString(set)).isEqualTo("[]");
1057+
}
1058+
1059+
@Test
1060+
void nullSafeConciseToStringForNonEmptyCollections() {
1061+
List<String> list = List.of("a", "b");
1062+
Set<Integer> set = Set.of(1);
1063+
assertThat(ObjectUtils.nullSafeConciseToString(list)).isEqualTo("[...]");
1064+
assertThat(ObjectUtils.nullSafeConciseToString(set)).isEqualTo("[...]");
1065+
}
1066+
1067+
@Test
1068+
void nullSafeConciseToStringForEmptyMaps() {
1069+
Map<String, String> map = new HashMap<String, String>();
1070+
assertThat(ObjectUtils.nullSafeConciseToString(map)).isEqualTo("{}");
1071+
}
1072+
1073+
@Test
1074+
void nullSafeConciseToStringForNonEmptyMaps() {
10481075
Map<String, Integer> map = Map.of("a", 1, "b", 2, "c", 3);
1049-
assertThat(ObjectUtils.nullSafeConciseToString(map)).startsWith(prefix(map.getClass()));
1076+
assertThat(ObjectUtils.nullSafeConciseToString(map)).isEqualTo("{...}");
10501077
}
10511078

10521079
@Test

0 commit comments

Comments
 (0)