The use-case
Assuming I have a source data structure that allows duplicate keys, something like a Collection<Map.Entry<String, Object>>, i.e. a hypothetical super type of Map<String, Object>. That type's string representation might look like this:
+--+--+-----+
|ID|ID|VALUE|
+--+--+-----+
| 1| 2| a|
| 1| 3| b|
+--+--+-----+
Now I would like to use Jackson to serialise the above source data structure to the most logical JSON representation, given that JSON also allows for duplicate keys, e.g. like this:
[{
"ID": 1,
"ID": 2,
"VALUE": "a"
}, {
"ID": 1,
"ID": 3,
"VALUE": "b"
}]
A tempting, but unclean solution
A tempting approach here would be to let the source data structure just implement Map<String, Object>, violating the Map contract, which reads:
A map cannot contain duplicate keys; each key can map to at most one value.
And just make sure Map.entrySet() produces the duplicate keys and their values, hoping that Jackson uses Map.entrySet() instead of Map.keySet() and then Map.get(). This feels very fishy, because:
- The
Mapcontract is violated (as well as theSetcontract for the sets returned byMap.entrySet()andMap.keySet()) - By consequence, a few methods don't work as expected, including
Map.get(), which can only produce one of the two conflicting values. - The
Mapcould be mutable, but not resizable, just likeArrays.asList(), which seems rather unprecedented and thus confusing (e.g.remove()andclear()don't work,put(),putAll()only work to mutate existing key/value pairs,putIfAbsent()is weird, because it doesn't work when a key is absent) - While the above may be acceptable for the mere serialisation use-case, the source data structure is used for many other purposes, and users would now get a flawed
Maprepresentation of it, for all non-serialisation use-cases as well.
Hoping for a better solution
Is there a better out-of-the-box way to support duplicate keys when serialising data with Jackson, or do I have to implement a JsonSerializer for that purpose?
For context, the real-world source data structure is a jOOQ Record