Description
The use case concerns X500Principal (aka "distinguished name") which can be mapped from/to byte array using a mixin class. Jackson serializes byte arrays as base64 strings by default. However, this failes when X500Principal is used as a Map key. In that case, the resulting byte array is serialized using toString(), which yields a useless output.
Complete example:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.x500.X500Principal;
public class Example
{
public static void main(String[] args) throws Exception
{
Map<X500Principal, X500Principal> values = new HashMap<>();
values.put(new X500Principal("CN=Mike"), new X500Principal("CN=John"));
new ObjectMapper()
.addMixIn(X500Principal.class, X500PrincipalMixin.class)
.writeValue(System.out, values);
}
private static final class X500PrincipalMixin
{
@JsonCreator
public X500PrincipalMixin(byte[] name) { throw new UnsupportedOperationException(); }
@JsonIgnore
public X500PrincipalMixin(String name) { throw new UnsupportedOperationException(); }
@JsonValue
public byte[] getEncoded() { throw new UnsupportedOperationException(); }
}
}
This outputs {"[B@1753acfe":"MA8xDTALBgNVBAMTBEpvaG4="}
. The value is correctly serialized as a base64 string, but the key isn't. I tested this with 2.8.6, 2.8.7 and 2.9.0.pr1. I haven't tested deserialization so far.
(Note that X500Principal cannot, in general, be serialized in its string representation (i.e., as per getName() and the String constructor), because the byte representation is the authoritative one and doesn't round-trip through the string representation in the general case. Therefore a serialization based on the byte array is necessary.)