Недавно я столкнулся с любопытным поведением во время де- / сериализации перечислений в / из 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!)
}
}




Перечисления 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());