我在我的java web app中使用gson将我的api模型序列化为json对象。
我已经成功地在版本化模型中使用了它的注解,但是我无法序列化Enum对象。
Action.class
public enum Action {
@SerializedName("create") CREATE,
@SerializedName("read") READ;
}尝试序列化一个Hashtable或另一个使用此枚举的pojo时,我得到了大写字母的字符串。
...
Gson gson = new GsonBuilder.create();
Hashtable<Action, String> table = new Hashtable<>();
table.put(Action.CREATE, "");
gson.toJson(table) // => { "CREATE" : "" } instead of { "create" : "" }
...我做错了什么?
发布于 2017-02-07 19:18:16
除了对您的问题的评论( MapTypeAdapterFactory不是@SerializedName-aware)解释了为什么它不适用于地图,并建议如果可能的话,您可以使用自定义JsonSerializer,如果您确实必须使用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。输出:
{"create":"item"}
请注意,这只适用于键,并且不会影响可能为序列化映射中的值的枚举显示的@SerializedName。上面的示例也可以修改为自动处理任何枚举,而不需要在GsonBuilder中注册每个这样的映射或哈希表(必须重新分析每个serialize方法中的@SerializedName注释,可能使用缓存机制),但它将为您提供一些设计选择。
https://stackoverflow.com/questions/42085301
复制相似问题