Сериализовать UUID как каноническую шестнадцатеричную строку в JSON с помощью JSON-B

UUID

универсальный уникальный идентификатор (UUID) - это 128-битное значение. Представлен в Java классом java.util.UUID.

Шестигранная строка

Для отображения и для сериализации он канонически отформатирован как шестнадцатеричная строка из 36 символов, разбитая на пять групп, разделенных дефисом. Например:
fd95cb46-8ec3-11e8-9eb6-529269fb1459

При сериализации с использованием стандартных Java API XML и JSON я ожидаю эту шестнадцатеричную строку. Работал с XML, но не с JSON. Я не использую никаких аннотаций ни для XML, ни для JSON. Мой простой POJO ничего не знает ни о XML, ни о JSON.

XML = успех ?

Когда я создаю XML, используя стандартную структуру привязки XML JSR 222: Архитектура JavaTM для привязки XML (JAXB) 2.0, успех. Я получаю шестнадцатеричную строку, как и ожидалось. См. Последний элемент этого фрагмента:

<?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 = сбой ?

Когда я запускаю тот же объект panel через стандартную структуру привязки JSON JSR 367: API JavaTM для привязки JSON (JSON-B), происходит сбой. Вместо ожидаемой шестнадцатеричной строки я получаю числа.

{"connected":"3.4kVA","fedFrom":"PANEL 'EHE1' & ATS-EM","grounding":"ground bus","id":{"leastSignificantBits":-5323841289984462261,"mostSignificantBits":-8515942329042973684},

Если вы прокрутите страницу, вы увидите, что UUID с именем id представлен в виде пары чисел, а не в виде шестнадцатеричной строки:

"id":{"leastSignificantBits":-5323841289984462261,"mostSignificantBits":-8515942329042973684}

Есть ли способ заставить привязку JSON вести себя так, как привязка XML? Мне нужна шестнадцатеричная строка, а не пара 64-битных чисел.

И, конечно, это маршалированное значение должно работать, когда оно не маршалируется, повторно гидратируется в объект Java.

UUID не является поддерживаемым типом JSON-B, поэтому вам, вероятно, придется реализовать свой собственный адаптер или сериализатор / десериализатор (json-b.net/users-guide.html).
Philipp 24.07.2018 00:28

@Philipp UUID также не является типом данных, известным в XML. Просто позвонив в java.util.UUID::toString, вы сделаете свою работу. Тем не менее, JSON-B изо всех сил пытается сгенерировать пару 64-битных чисел.

Basil Bourque 24.07.2018 00:35

Что ж, вы можете назвать это «не с дороги» или нет, но с точки зрения JSON-B UUID - это просто объект (неизвестного типа), который имеет два атрибута (longs), которые JSON-B сериализует в два атрибута, которые вы обратите внимание на ваш вывод: leastSignificantBits и mostSignificantBits. Кстати. у других преобразователей JSON была / есть такая же проблема, например, GSON: github.com/google/gson/issues/79

Philipp 24.07.2018 00:44
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
3
1 949
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В спецификации JSON-B не упоминается тип UUID, поэтому реализация зависит от того, предоставляет ли он (де) сериализатор из коробки. Однако, если вы используете Eclipse Yasson (JSON-B ref impl), он по умолчанию предоставляет сериализатор UUID (de). Я не уверен, что другие подразумеваемые JSON-B (например, Apache Johnzon) предоставляют по умолчанию.

Если вы используете Yasson, я бы рекомендовал открыть ошибку на их репозиторий на GitHub, потому что это должно работать.


Пользовательский способ

Если вы используете реализацию JSON-B, которая по умолчанию не предоставляет адаптеры UUID, вы можете создать и зарегистрировать свой собственный адаптер типа:

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);
    }

}

Самый простой способ зарегистрировать адаптер - создать экземпляр Jsonb:

Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withAdapters(new MyUUIDAdapter()));

Однако, если вы не контролируете создание экземпляра вашего Jsonb (например, JAX-RS делает это под прикрытием), вы можете аннотировать поле / метод для использования адаптера:

public class Panel {
    @JsonbTypeAdapter(MyUUIDAdapter.class)
    public UUID id;
}

Другие вопросы по теме