除了对您问题的评论(即
MapTypeAdapterFactory
不支持
@SerializedName
),说明它为什么不能用于映射,并建议在可能的情况下更改数据交换模型外,如果您确实必须使用像
Map
或
Hashtable
这样的数据包,您可以使用自定义的
JsonSerializer
:
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
的特定枚举。而序列化器本身:
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
。输出结果为:
{"create":"item"}
请注意,这仅适用于键,不影响在序列化映射中作为值的枚举可能出现的
@SerializedName
。上面的示例也可以重构为自动处理任何枚举,而不需要每个这样的映射或哈希表在
GsonBuilder
中注册(可能使用缓存机制在每个
serialize
方法中重新分析
@SerializedName
注释),但这是您需要做出的设计选择。
@SerializedName
作为映射键存在特定的问题? - chrylis -cautiouslyoptimistic-enum
和@SerializedName
,那么它们将能够正常工作。但是据我所知,enum
的@SerializedName
将出现在JSON对象的值中而不是键中。 - Lyubomyr Shaydariv