В поисках объяснения этого любопытного поведения во время де / сериализации перечислений - PullRequest
0 голосов
/ 07 января 2019

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

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

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

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

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

1 Ответ

0 голосов
/ 07 января 2019

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

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

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

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

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