【问题标题】:Lower case enum Gson小写枚举 Gson
【发布时间】:2015-03-15 02:43:57
【问题描述】:

我需要使用 Gson 输出枚举值,由于客户端限制需要小写。

例如,CLOSE_FILE 将是 close_file

有没有一种简单的方法可以做到这一点?我看过创建一个实现JsonSerializer 的类,但看起来我必须手动序列化整个类(这很复杂)是这种情况吗?

【问题讨论】:

    标签: java json gson


    【解决方案1】:

    如果您可以控制enum 类型,请使用@SerializedName 注释其成员并为其赋予适当的序列化值。例如,

    enum Action {
        @SerializedName("close_file")
        CLOSE_FILE;
    }
    

    如果您无法控制enum,请在创建Gson 实例时提供自定义TypeAdapter。例如,

    Gson gson = new GsonBuilder().registerTypeAdapter(Action.class, new TypeAdapter<Action>() {
    
        @Override
        public void write(JsonWriter out, Action value) throws IOException {
            out.value(value.name().toLowerCase());
        }
    
        @Override
        public Action read(JsonReader in) throws IOException {
            return Action.valueOf(in.nextString().toUpperCase());
        }
    }).create();
    

    【讨论】:

    • 问题:类型适配器会将all值重写为小写?我在代码中没有看到任何特定于枚举的内容。
    • @frieder 类型适配器仅为枚举类型注册。只有在序列化该类型的值时才会调用它。
    • 哦,是的,现在我看到了 - 它已为特定的 Action 枚举注册。哦。 :P 是否可以注册所有枚举类型?
    • @friederbluemle Enum 是所有枚举类型的超类型。序列化可能很容易,只需小写 name(),但反序列化需要更多关于反序列化到的实际类型的信息。
    【解决方案2】:

    如果要将所有枚举序列化为小写,可以使用此代码

    Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(Enum.class, new EnumToLowerCaseJsonConverter()).create();
    
    public final class EnumToLowerCaseJsonConverter implements JsonSerializer<Enum<?>>, JsonDeserializer<Enum<?>> {
        private static Map<String, Class<? extends Enum<?>>> typesToClass = new HashMap<>();
        
        @Override
        public JsonElement serialize(final Enum<?> src, final Type typeOfSrc,
                final JsonSerializationContext context) {
            if (src == null) {
                return JsonNull.INSTANCE;
            }
            return new JsonPrimitive(src.name().toLowerCase());
        }
    
        @SuppressWarnings("unchecked")
        @Override
        public Enum<?> deserialize(final JsonElement json, final Type typeOfT,
                final JsonDeserializationContext context) throws JsonParseException {
            if (json == null || json.isJsonNull()) {
                return null;
            }
            
            if (!json.isJsonPrimitive() || !json.getAsJsonPrimitive().isString()) {
                throw new JsonParseException(
                        "Expecting a String JsonPrimitive, getting " + json.toString());
            }
            
            try {
                final String enumClassName = typeOfT.getTypeName();
                Class<? extends Enum<?>> clazz = typesToClass.get(enumClassName);
                if (clazz == null) {
                    clazz = (Class<? extends Enum<?>>) Class.forName(enumClassName);
                    typesToClass.put(enumClassName, clazz);
                }
                
                return Enum.valueOf((Class) clazz, json.getAsString().toUpperCase());
            } catch (final ClassNotFoundException e) {
                throw new JsonParseException(e);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      一个易于使用的特定类型适配器:

      Gson gson = new GsonBuilder().registerTypeAdapter(Action.class, new EnumToLowerCaseTypeAdapter<>(Action.class)).create();
      
      public final class EnumToLowerCaseTypeAdapter<T extends Enum<?>> extends TypeAdapter<T> {
          private final Class<T> clazz;
          
          public EnumToLowerCaseTypeAdapter(final Class<T> clazz) {
              this.clazz = clazz;
          }
      
          @Override
          public void write(final JsonWriter out, final T value) throws IOException {
              if (value == null) {
                  out.nullValue();
              } else {
                  out.value(value.name().toLowerCase());
              }
          }
      
          @SuppressWarnings("unchecked")
          @Override
          public T read(final JsonReader in) throws IOException {
              
              switch (in.peek()) {
                  case NULL:
                      in.nextNull();
                      return null;
                  default:
                      final String value = in.nextString();
                      return (T) Enum.valueOf((Class) clazz, value.toUpperCase());
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-02-22
        • 1970-01-01
        • 2017-03-02
        • 2023-01-18
        • 2015-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-16
        相关资源
        最近更新 更多