小写枚举Gson

时间:2015-03-15 02:43:57

标签: java json gson

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

例如CLOSE_FILEclose_file

有一种简单的方法吗?我已经看过创建一个实现JsonSerializer的类,但看起来我必须手动序列化整个类(这很复杂)是这样的吗?

3 个答案:

答案 0 :(得分:18)

如果您可以控制enum类型,请使用@SerializedName为其成员添加注释,并为其指定相应的序列化值。例如,

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

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

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();

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

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());
        }
    }
}