如何制作符合 i18n 标准的 EnumTypeAdapter?
How can I make an i18n compliant EnumTypeAdapter?
我正在研究一个很好的国际化解决方案 Enums
通过 Gson 反序列化 (.toJson)。
现在我有了它:
private static final class GenericEnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
private ResourceBundle bundle = ResourceBundle.getBundle("Messages");
private Class<T> classOfT;
public GenericEnumTypeAdapter(Class<T> classOfT) {
this.classOfT = classOfT;
}
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return Enum.valueOf(classOfT, in.nextString());
}
public void write(JsonWriter out, T value) throws IOException {
out.value(value == null ? null : bundle.getString("enum." + value.getClass().getSimpleName() + "."
+ value.name()));
}
}
这个解决方案的问题是:对于每个枚举,你应该注册一个新的适配器:
gsonBuilder.registerTypeAdapter(EventSensorState.class,
new GenericEnumTypeAdapter<>(FirstEnum.class)
有人有更好的想法吗?
使用 TypeAdapterFactory
生成所有适配器。请参阅 How do I implement TypeAdapterFactory in Gson?
要将您的TypeAdapter
转换为TypeAdapterFactory
,关键是正确检测class,然后使用create
方法。警告:此解决方案将在您的系统中注册每种类型的枚举;您可能需要调整它以仅与实现特定接口的 Enum
一起使用,或者将 Enum
class 注册到子 class 等。我创建了一个 EnumGenerator
class 完成阅读转换的大部分工作,您应该可以自己弄清楚。
public class EnumAdapterFactory implements TypeAdapterFactory {
private final ResourceBundle bundle;
private final EnumGenerator generator;
public EnumAdapterFactory(ResourceBundle bundle, EnumGenerator generator) {
this.bundle = bundle;
this.generator = generator;
}
@SuppressWarnings("unchecked")
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (!Enum.class.isAssignableFrom(type.getRawType())) return null;
return (TypeAdapter<T>) new GenericEnumTypeAdapter();
}
private final class GenericEnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return generator.create(in.nextString());
}
public void write(JsonWriter out, T value) throws IOException {
if(value == null) {
out.nullValue();
return;
}
out.value(bundle.getString("enum."
+ value.getClass().getSimpleName() + "."
+ value.name()));
}
}
}
和EnumGenerator
的接口:
public interface EnumGenerator {
<T extends Enum<T>> T create(String nextString);
}
我正在研究一个很好的国际化解决方案 Enums
通过 Gson 反序列化 (.toJson)。
现在我有了它:
private static final class GenericEnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
private ResourceBundle bundle = ResourceBundle.getBundle("Messages");
private Class<T> classOfT;
public GenericEnumTypeAdapter(Class<T> classOfT) {
this.classOfT = classOfT;
}
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return Enum.valueOf(classOfT, in.nextString());
}
public void write(JsonWriter out, T value) throws IOException {
out.value(value == null ? null : bundle.getString("enum." + value.getClass().getSimpleName() + "."
+ value.name()));
}
}
这个解决方案的问题是:对于每个枚举,你应该注册一个新的适配器:
gsonBuilder.registerTypeAdapter(EventSensorState.class,
new GenericEnumTypeAdapter<>(FirstEnum.class)
有人有更好的想法吗?
使用 TypeAdapterFactory
生成所有适配器。请参阅 How do I implement TypeAdapterFactory in Gson?
要将您的TypeAdapter
转换为TypeAdapterFactory
,关键是正确检测class,然后使用create
方法。警告:此解决方案将在您的系统中注册每种类型的枚举;您可能需要调整它以仅与实现特定接口的 Enum
一起使用,或者将 Enum
class 注册到子 class 等。我创建了一个 EnumGenerator
class 完成阅读转换的大部分工作,您应该可以自己弄清楚。
public class EnumAdapterFactory implements TypeAdapterFactory {
private final ResourceBundle bundle;
private final EnumGenerator generator;
public EnumAdapterFactory(ResourceBundle bundle, EnumGenerator generator) {
this.bundle = bundle;
this.generator = generator;
}
@SuppressWarnings("unchecked")
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (!Enum.class.isAssignableFrom(type.getRawType())) return null;
return (TypeAdapter<T>) new GenericEnumTypeAdapter();
}
private final class GenericEnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return generator.create(in.nextString());
}
public void write(JsonWriter out, T value) throws IOException {
if(value == null) {
out.nullValue();
return;
}
out.value(bundle.getString("enum."
+ value.getClass().getSimpleName() + "."
+ value.name()));
}
}
}
和EnumGenerator
的接口:
public interface EnumGenerator {
<T extends Enum<T>> T create(String nextString);
}