Ищете объяснение этого любопытного поведения во время де- / сериализации перечислений

Недавно я столкнулся с любопытным поведением во время де- / сериализации перечислений в / из JSON.

Я превратил соответствующую часть в простой пример (см. Код ниже). в основном у вас есть список, содержащий записи перечисления. Вы сериализуете список, а затем десериализуете его. если вы проверите этот новый (десериализованный) список, если он содержит определенные записи перечисления, вы всегда получите ответ «false», даже если список фактически содержит запись.

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

Я хотел бы понять, почему это происходит и как этого избежать. моей целью было бы снова получить список записей перечисления после десериализации, а не список строк.

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;

public class Test {

    enum TYPE {
        SMALL, MEDIUM, LARGE
    }

    public static void main(String[] args) {

        List<TYPE> myList = new ArrayList<>();

        myList.add( TYPE.MEDIUM );

        // serialize
        String serializedJsonString = JsonbBuilder.create(new JsonbConfig().withLocale(Locale.GERMAN).withFormatting(true)).toJson(myList);

        // deserialize
        @SuppressWarnings("unchecked")
        List<TYPE> mySecondList = JsonbBuilder.create(new JsonbConfig().withLocale(Locale.GERMAN).withFormatting(true)).fromJson(serializedJsonString, List.class);

        System.out.println( myList.contains( TYPE.MEDIUM ) );       // will be true (as expected)

        System.out.println( mySecondList.contains( TYPE.MEDIUM ) ); // will be false (surprising!)
        System.out.println( mySecondList.contains( "MEDIUM" ) );    // will be true (surprising!)
    }
}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
91
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Перечисления Java по умолчанию сериализуются в строки, так как для них нет лучшего типа JSON по умолчанию. (Вы можете настроить их для сериализации в целые числа, если хотите.)

При десериализации вы должны указать парсеру Jsonb преобразовать строки JSON в перечисление, в противном случае он десериализует их в строки Java по умолчанию.

Вы не сделали этого в приведенном выше примере, потому что вы запросили List.class (т.е. List<?>), а не список перечислений TYPE (List<TYPE>). В Java это сложно сделать из-за стирания типов. (Обратите внимание, что вы должны были пометить код как «непроверенный», потому что компилятор знает, что ваша версия не будет работать.) В документации JsonB этот случай обсуждается явно: http://json-b.net/docs/user-guide.html#mapping-a-generic-collection

Попробуйте что-нибудь вроде:

List<TYPE> mySecondList = jsonb.fromJson(result, new ArrayList<TYPE>(){}.getClass().getGenericSuperclass());

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