首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Gson枚举序列化

Gson枚举序列化
EN

Stack Overflow用户
提问于 2017-02-07 16:46:23
回答 2查看 5K关注 0票数 4

我在我的java web app中使用gson将我的api模型序列化为json对象。

我已经成功地在版本化模型中使用了它的注解,但是我无法序列化Enum对象。

Action.class

代码语言:javascript
复制
public enum Action {

    @SerializedName("create") CREATE,
    @SerializedName("read") READ;

}

尝试序列化一个Hashtable或另一个使用此枚举的pojo时,我得到了大写字母的字符串。

代码语言:javascript
复制
...
Gson gson = new GsonBuilder.create();
Hashtable<Action, String> table = new Hashtable<>();
table.put(Action.CREATE, "");
gson.toJson(table) // => { "CREATE" : "" } instead of { "create" : "" }
...

我做错了什么?

EN

回答 2

Stack Overflow用户

发布于 2018-06-08 01:27:16

当您将enableComplexMapKeySerialization选项添加到Gson实例时,您的代码可以正常工作。

https://google.github.io/gson/apidocs/com/google/gson/GsonBuilder.html#enableComplexMapKeySerialization--

Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();

票数 4
EN

Stack Overflow用户

发布于 2017-02-07 19:18:16

除了对您的问题的评论( MapTypeAdapterFactory不是@SerializedName-aware)解释了为什么它不适用于地图,并建议如果可能的话,您可以使用自定义JsonSerializer,如果您确实必须使用MapHashtable之类的数据包

代码语言:javascript
复制
private static final TypeToken<?> actionToUnknownHashtableTypeToken = new TypeToken<Hashtable<Action, ?>>() {
};

请注意,类型标记用于更精确地确定可序列化枚举的目标,并缓存内部序列化名称映射:

代码语言:javascript
复制
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的每个特定枚举都可以单独注册。以及序列化程序本身:

代码语言:javascript
复制
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注释,可能使用缓存机制),但它将为您提供一些设计选择。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42085301

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档