2

UUID

A universally unique identifier (UUID) is a 128-bit value. Represented in Java by the java.util.UUID class.

Hex string

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.

XML = success

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' &amp; ATS-EM</fedFrom>
    <grounding>ground bus</grounding>
    <id>89d14b92-35ae-4c0c-b61d-ea8dbdeb324b</id>

JSON = fail

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 1
    `UUID` is not a supported JSON-B type, thus you probably have to implement your own adapter or serializer/deserializer (http://json-b.net/users-guide.html). – Philipp Jul 23 '18 at 22:28
  • 1
    @Philipp Neither is UUID a data type known to XML. Merely calling `java.util.UUID::toString` gets the job done. Yet JSON-B is going out of its way to generate a pair of 64-bit numbers. – Basil Bourque Jul 23 '18 at 22:35
  • 1
    Well you may call it "out of the way" or not, but from JSON-B's perspective `UUID` is just an object (of an unknown type), which has two attributes (longs), which JSON-B serializes into the two attributes you observe in your output: `leastSignificantBits` and `mostSignificantBits`. Btw. other JSON mappers had/have the same problem, e.g., `GSON`: https://github.com/google/gson/issues/79 – Philipp Jul 23 '18 at 22:44

1 Answers1

4

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.


Custom way

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;
}
Andy Guibert
  • 41,446
  • 8
  • 38
  • 61