-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Search before asking
- I searched in the issues and found nothing similar.
Describe the bug
We have a global ObjectMapper configured in springboot used to convert objects to JSON for REST return values as well as sending objects over JMS and other places.
To have somewhat deterministic ordering of the JSON elements, we have turned on
objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
This has been working fine for years, but now one of the other teams have implemented a map of exchange rates
Map<java.util.Currency, internal.dto.ExchangeRate> exchangeRates
When the system tries to convert this to JSON, it causes an exception:
Caused by: java.lang.ClassCastException: class java.util.Currency cannot be cast to class java.lang.Comparable (java.util.Currency and java.lang.Comparable are in module java.base of loader 'bootstrap')
at java.base/java.util.TreeMap.compare(TreeMap.java:1569)
at java.base/java.util.TreeMap.addEntryToEmptyMap(TreeMap.java:776)
at java.base/java.util.TreeMap.put(TreeMap.java:785)
at java.base/java.util.TreeMap.put(TreeMap.java:534)
at java.base/java.util.AbstractMap.putAll(AbstractMap.java:281)
at java.base/java.util.TreeMap.putAll(TreeMap.java:326)
at java.base/java.util.TreeMap.<init>(TreeMap.java:187)
at com.fasterxml.jackson.databind.ser.std.MapSerializer._orderEntries(MapSerializer.java:1182)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:754)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:720)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:35)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:733)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774)
... 32 common frames omitted
The solution seems to be to disable map sorting feature, but then we lose the huge value this has given everywhere else with deterministic ordering.
In this situation, would be preferable if the fallback was just not to sort a map that can't be sorted. Perhaps warrants a different feature flag, ORDER_COMPARABLE_MAP_ENTRIES_BY_KEYS?
Some way to specify global sorting comparators would be nice, but since there is always possibility a new Map would be created using keys that weren't sorted, defaulting to converting/sending message (even if not sorted) would still be preference.
That secondary ability to sort seems to already be raised here: #2162
But still feel this is separate issue/bug, ability to keep sorting feature without failing on unsortables.
Version Information
2.14
Reproduction
private static class Entity {
private Map<Currency, String> exampleMap = new HashMap<>();
public Map<Currency, String> getExampleMap() {
return exampleMap;
}
public void setExampleMap(Map<Currency, String> exampleMap) {
this.exampleMap = exampleMap;
}
}
@Test
void testDeserializationCurrencyMap3() throws IOException {
final Entity entity = new Entity();
final Map<Currency, String> exampleMap = entity.getExampleMap();
exampleMap.put(Currency.getInstance("GBP"), "GBP_TEXT");
exampleMap.put(Currency.getInstance("AUD"), "AUD_TEXT");
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
objectMapper.writeValueAsString(entity);
}
Expected behavior
No response
Additional context
No response