Использование Enums при parsingе JSON с помощью GSON

Это связано с предыдущим вопросом, который я задал здесь ранее

Разбор JSON с использованием Gson

Я пытаюсь разобрать тот же JSON, но теперь я немного изменил свои classы.

{ "lower": 20, "upper": 40, "delimiter": " ", "scope": ["${title}"] } 

Мой class теперь выглядит так:

 public class TruncateElement { private int lower; private int upper; private String delimiter; private List scope; // getters and setters } public enum AttributeScope { TITLE("${title}"), DESCRIPTION("${description}"), private String scope; AttributeScope(String scope) { this.scope = scope; } public String getScope() { return this.scope; } } 

Этот код генерирует исключение,

 com.google.gson.JsonParseException: The JsonDeserializer EnumTypeAdapter failed to deserialized json object "${title}" given the type class com.amazon.seo.attribute.template.parse.data.AttributeScope at 

Исключение понятно, потому что в соответствии с моим предыдущим вопросом GSON ожидает, что объекты Enum будут фактически созданы как

 ${title}("${title}"), ${description}("${description}"); 

Но так как это синтаксически невозможно, какие рекомендуемые решения, обходные пути?

Из документации для Gson :

Gson предоставляет сериализацию и десериализацию по умолчанию для Enums … Если вы предпочитаете изменять представление по умолчанию, вы можете сделать это, зарегистрировав адаптер типа через GsonBuilder.registerTypeAdapter (Type, Object).

Ниже приводится один такой подход.

 import java.io.FileReader; import java.lang.reflect.Type; import java.util.List; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; public class GsonFoo { public static void main(String[] args) throws Exception { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(AttributeScope.class, new AttributeScopeDeserializer()); Gson gson = gsonBuilder.create(); TruncateElement element = gson.fromJson(new FileReader("input.json"), TruncateElement.class); System.out.println(element.lower); System.out.println(element.upper); System.out.println(element.delimiter); System.out.println(element.scope.get(0)); } } class AttributeScopeDeserializer implements JsonDeserializer { @Override public AttributeScope deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { AttributeScope[] scopes = AttributeScope.values(); for (AttributeScope scope : scopes) { if (scope.scope.equals(json.getAsString())) return scope; } return null; } } class TruncateElement { int lower; int upper; String delimiter; List scope; } enum AttributeScope { TITLE("${title}"), DESCRIPTION("${description}"); String scope; AttributeScope(String scope) { this.scope = scope; } } 

Я хочу немного расширить NAZIK / user2724653 ответ (для моего случая). Вот код Java:

 public class Item { @SerializedName("status") private Status currentState = null; // other fields, getters, setters, constructor and other code... public enum Status { @SerializedName("0") BUY, @SerializedName("1") DOWNLOAD, @SerializedName("2") DOWNLOADING, @SerializedName("3") OPEN } } 

в json-файле у вас есть только поле "status": "N", , где N = 0,1,2,3 – зависит от значений состояния. Так вот, GSON отлично работает со значениями для вложенного classа enum . В моем случае я проанализировал список Items из массива json :

 List items = new Gson().>fromJson(json, new TypeToken>(){}.getType()); 

Использовать аннотацию @SerializedName :

 @SerializedName("${title}") TITLE, @SerializedName("${description}") DESCRIPTION 

С переходом enums GSON версии 2.2.2 будет легко сортироваться и легко сортироваться.

 import com.google.gson.annotations.SerializedName; enum AttributeScope { @SerializedName("${title}") TITLE("${title}"), @SerializedName("${description}") DESCRIPTION("${description}"); private String scope; AttributeScope(String scope) { this.scope = scope; } public String getScope() { return scope; } } 

Следующий fragment устраняет необходимость в явном Gson.registerTypeAdapter(...) , используя аннотацию @JsonAdapter(class) , доступную с Gson 2.3 (см. Комментарий pm_labs ).

 @JsonAdapter(Level.Serializer.class) public enum Level { WTF(0), ERROR(1), WARNING(2), INFO(3), DEBUG(4), VERBOSE(5); int levelCode; Level(int levelCode) { this.levelCode = levelCode; } static Level getLevelByCode(int levelCode) { for (Level level : values()) if (level.levelCode == levelCode) return level; return INFO; } static class Serializer implements JsonSerializer, JsonDeserializer { @Override public JsonElement serialize(Level src, Type typeOfSrc, JsonSerializationContext context) { return context.serialize(src.levelCode); } @Override public Level deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { try { return getLevelByCode(json.getAsNumber().intValue()); } catch (JsonParseException e) { return INFO; } } } } 

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

 public class EnumTypeAdapter > extends TypeAdapter { private final Map nameToConstant = new HashMap<>(); private final Map constantToName = new HashMap<>(); public EnumTypeAdapter(Class classOfT) { for (T constant : classOfT.getEnumConstants()) { Integer name = constant.ordinal(); nameToConstant.put(name, constant); constantToName.put(constant, name); } } @Override public T read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } return nameToConstant.get(in.nextInt()); } @Override public void write(JsonWriter out, T value) throws IOException { out.value(value == null ? null : constantToName.get(value)); } public static final TypeAdapterFactory ENUM_FACTORY = new TypeAdapterFactory() { @SuppressWarnings({"rawtypes", "unchecked"}) @Override public  TypeAdapter create(Gson gson, TypeToken typeToken) { Class rawType = typeToken.getRawType(); if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) { return null; } if (!rawType.isEnum()) { rawType = rawType.getSuperclass(); // handle anonymous subclasses } return (TypeAdapter) new EnumTypeAdapter(rawType); } }; } 

Затем просто зарегистрируйте завод.

 Gson gson = new GsonBuilder() .registerTypeAdapterFactory(EnumTypeAdapter.ENUM_FACTORY) .create(); 

используйте этот метод

 GsonBuilder.enableComplexMapKeySerialization(); 
  • Как читать json-файл в java с помощью простой библиотеки JSON
  • asp.net asmx веб-сервис возвращает xml вместо json
  • Игнорирование новых полей объектов JSON с использованием Jackson
  • Передача переменной bash в jq select
  • Ошибка jQuery AJAX в IE
  • Удаление десериализации файла JSON с помощью JavaScriptSerializer ()
  • Почему, когда конструктор аннотируется с помощью @JsonCreator, его аргументы должны быть аннотированы с помощью @JsonProperty?
  • Разбор JSON из URL
  • как получить значения spinner в textview
  • «JSON» - неопределенная ошибка только в IE
  • Разбор json в java-объекты в spring-mvc
  • Давайте будем гением компьютера.