小写枚举 Gson
Lower case enum Gson
我需要使用 Gson 输出枚举值,由于客户端限制,它需要小写。
例如 CLOSE_FILE
将是 close_file
。
有没有简单的方法可以做到这一点?我看过制作一个实现 JsonSerializer
的 class,但看起来我必须手动序列化整个 class(这很复杂)是这种情况吗?
如果您可以控制 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();
如果你想将所有枚举序列化为小写,你可以使用这段代码
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);
}
}
}
一个易于使用的特定类型适配器:
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());
}
}
}
我需要使用 Gson 输出枚举值,由于客户端限制,它需要小写。
例如 CLOSE_FILE
将是 close_file
。
有没有简单的方法可以做到这一点?我看过制作一个实现 JsonSerializer
的 class,但看起来我必须手动序列化整个 class(这很复杂)是这种情况吗?
如果您可以控制 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();
如果你想将所有枚举序列化为小写,你可以使用这段代码
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);
}
}
}
一个易于使用的特定类型适配器:
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());
}
}
}