A universally unique identifier (UUID) is a 128-bit value. Represented in Java by the java.util.UUID
class.
For display and for serialization, it is canonically formatted as a 36-character hexadecimal string arranged in five groups delimited by a hyphen. For example:fd95cb46-8ec3-11e8-9eb6-529269fb1459
When serializing using the Java-standard XML & JSON APIs I expect this hex string. Worked for XML, but failed for JSON. I am using no annotations of any kind for either XML or JSON. My simple POJO knows nothing of XML nor JSON.
When I produce XML using the standard XML-binding framework of JSR 222: JavaTM Architecture for XML Binding (JAXB) 2.0, success. I get the hex string as expected. See last element of this snippet:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<panel>
<connected>3.4kVA</connected>
<fedFrom>PANEL 'EHE1' & ATS-EM</fedFrom>
<grounding>ground bus</grounding>
<id>89d14b92-35ae-4c0c-b61d-ea8dbdeb324b</id>
When I run that same panel
object through the standard JSON-binding framework of JSR 367: JavaTM API for JSON Binding (JSON-B), failure. Instead of the expected hex string, I get numbers.
{"connected":"3.4kVA","fedFrom":"PANEL 'EHE1' & ATS-EM","grounding":"ground bus","id":{"leastSignificantBits":-5323841289984462261,"mostSignificantBits":-8515942329042973684},
If you scroll over, you will see the UUID named id
is presented as a pair of numbers rather than as a hex string:
"id":{"leastSignificantBits":-5323841289984462261,"mostSignificantBits":-8515942329042973684}
Is there some way to get the JSON binding to behave as the XML binding does? I want the hex string, not a pair of 64-bit numbers.
And of course this marshaled value should work when unmarshaled, re-hydrated into a Java object.
The JSON-B spec makes no mention of the UUID type, so it's up to the implementation whether or not it provides a (de)serializer out of the box. However, if you are using Eclipse Yasson (the JSON-B ref impl), it does provide a UUID (de)serializer by default. I'm not sure what other JSON-B impls (such as Apache Johnzon) provide by default.
If you are using Yasson, I would recommend opening a bug on their GitHub repo, because this should work.
If you are using a JSON-B implementation that does not provide UUID adapters by default, you can create and register your own type adapter:
public static class MyUUIDAdapter implements JsonbAdapter<UUID, String> {
@Override
public String adaptToJson(UUID obj) throws Exception {
return obj.toString();
}
@Override
public UUID adaptFromJson(String obj) throws Exception {
return UUID.fromString(obj);
}
}
The easiest way to register the adapter is when you create the Jsonb
instance:
Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withAdapters(new MyUUIDAdapter()));
However, if you don't control instantiation of your Jsonb
instance (e.g. JAX-RS is doing it under the covers) you can annotate the field/method to use the adapter on:
public class Panel {
@JsonbTypeAdapter(MyUUIDAdapter.class)
public UUID id;
}