除了您的问题的 cmets(MapTypeAdapterFactory 不是 @SerializedName-aware)解释了为什么它不适用于地图并建议尽可能更改您的数据交换模型,您可以使用自定义 @987654323 @如果你真的必须使用像Map或Hashtable这样的数据包:
private static final TypeToken<?> actionToUnknownHashtableTypeToken = new TypeToken<Hashtable<Action, ?>>() {
};
请注意,类型标记用于更精确地定位可序列化枚举并缓存内部序列化名称映射:
final Gson gson = new GsonBuilder()
.registerTypeAdapter(actionToUnknownHashtableTypeToken.getType(), getSerializedNameEnumHashtableJsonSerializer(Action.class))
.create();
final Hashtable<Action, String> table = new Hashtable<>();
table.put(CREATE, "item");
out.println(gson.toJson(table, actionToUnknownHashtableTypeToken.getType()));
还要注意toJson 方法的使用。因此,您创建的每个特定枚举 @SerializedName-aware 都可以单独注册。还有序列化器本身:
final class SerializedNameEnumHashtableJsonSerializer<K extends Enum<K>, V>
implements JsonSerializer<Hashtable<K, V>> {
private final Map<K, String> serializedNames;
private SerializedNameEnumHashtableJsonSerializer(final Map<K, String> serializedNames) {
this.serializedNames = serializedNames;
}
static <K extends Enum<K>, V> JsonSerializer<Hashtable<K, V>> getSerializedNameEnumHashtableJsonSerializer(final Class<K> enumClass) {
try {
final Map<K, String> serializedNames = new HashMap<>();
for ( final K enumConstant : enumClass.getEnumConstants() ) {
final String enumName = enumConstant.name();
final Field field = enumClass.getField(enumName);
final SerializedName serializedName = field.getAnnotation(SerializedName.class);
if ( serializedName != null ) {
serializedNames.put(enumConstant, serializedName.value());
}
}
return new SerializedNameEnumHashtableJsonSerializer<>(unmodifiableMap(serializedNames));
} catch ( final NoSuchFieldException ex ) {
throw new AssertionError(ex);
}
}
@Override
public JsonElement serialize(final Hashtable<K, V> hashtable, final Type type, final JsonSerializationContext context) {
final JsonObject jsonObject = new JsonObject();
for ( final Entry<K, V> e : hashtable.entrySet() ) {
final K key = e.getKey();
final String nameCandidate = serializedNames.get(key);
final String serializedName = nameCandidate != null ? nameCandidate : key.name();
jsonObject.add(serializedName, context.serialize(e.getValue()));
}
return jsonObject;
}
}
还要注意上面的序列化器只处理SerializedName.value,并不关心SerializedName.alternate。输出:
{"创建":"项目"}
请注意,这仅适用于键,不会影响@SerializedName,它可能出现在作为序列化映射中的值的枚举中。上面的示例也可以重新设计以自动处理任何枚举,并且不需要在 GsonBuilders 中注册每个这样的映射或哈希表(必须重新分析每个 serialize 方法中的 @SerializedName 注释,可能使用缓存机制),但它会为您提供一些设计选择。