FasterXML / FasterXML/jackson-databind
Map Key interface not serialized with both type serializer or keyUsing
- Dominant language
- Java
- Stars
- 3.7k
- Forks
- 1.5k
- Avg merge
- 3d 6h
- Merged PRs (30d)
- 28
Description
**Describe the bug**
In my application I have a `Map` where `KapuaId` is an interface, and has its own serializer (since I also use this type in other parts as a standalone object):
```
public class KapuaIdSerializer extends JsonSerializer {
@Override
public void serialize(KapuaId value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.toCompactId());
}
}
```
So, I first thought that registering the mixin for the standalone type would have also worked when serializing the `Map`:
```
objectMapper = new ObjectMapper();
objectMapper.addMixIn(KapuaId.class, KapuaIdMixin.class);
```
```
@JsonDeserialize(using = KapuaIdDeserializer.class)
@JsonSerialize(using = KapuaIdSerializer.class)
public interface KapuaIdMixin { }
```
But unfortunately it's not, since the `toString()` of the concrete type is returning:
```
{
"1": null,
"5667511473135966782": false,
"8466406404189434576": false
}
```
So I built a container object, where I used `@JsonValue` and `@JsonSerialize(keyUsing = KapuaIdSerializer.class)`, but nothing changed:
```
public class IsJobRunningMapResponse {
private final Map map;
public IsJobRunningMapResponse(Map map) {
this.map = map;
}
@JsonValue
@JsonSerialize(keyUsing = KapuaIdSerializer.class)
public Map getMap() {
return map;
}
}
```
But the result was the same. In the end I had to use a Converter for the whole container type, basically duplicating what `KapuaIdSerializer` was already doing:
```
public class IsJobRunningMapResponseSerializer extends JsonSerializer {
@Override
public void serialize(IsJobRunningMapResponse value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
for (Map.Entry entry : value.getMap().entrySet()) {
if (entry.getValue() == null) {
gen.writeNullField(entry.getKey().toCompactId());
} else {
gen.writeBooleanField(entry.getKey().toCompactId(), entry.getValue());
}
}
gen.writeEndObject();
}
```
And in the end the response was the one I expected, with `KapuaId` serialized correctly:
```
// KapuaId value coming from KapuaId.toCompactId()
{
"AQ": null,
"TqcLqDS4Wj4": false,
"dX63xIXNstA": false
}
```
So... I found a workaround, but I think that something is not ok with the key type serialization.
**Version information**
2.12.2
**To Reproduce**
If you have a way to reproduce this with:
Steps reproduced above. Full repository at https://github.com/lorthirk/kapua/tree/feature-multipleJobIsRunning/job-engine/app/resources/src/main/java/org/eclipse/kapua/job/engine/app
**Expected behavior**
`KapuaId` should have been serialized with its own serializer, or at least `keyUsing` should not have been ignored
**Additional context**
Using together with Jersey 2.23.2
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.