简体   繁体   中英

BiMap<UUID, String> being deserialized as BiMap<String, String> by Gson

public class BiMapTypeAdapterFactory implements TypeAdapterFactory {
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
        Type type = typeToken.getType();
        if (typeToken.getRawType() != BiMap.class
                || !(type instanceof ParameterizedType)) {
            return null;
        }
        return (TypeAdapter<T>) newBiMapAdapter(gson);
    }

    private <K, V> TypeAdapter<BiMap<K, V>> newBiMapAdapter(Gson gson) {
        TypeAdapter<Map<K, V>> mapTypeAdapter = gson.getAdapter(new TypeToken<Map<K, V>>() {});
        return new TypeAdapter<BiMap<K, V>>() {
            public void write(JsonWriter out, BiMap<K, V> value) throws IOException {
                mapTypeAdapter.write(out, value);
            }

            public BiMap<K, V> read(JsonReader in) throws IOException {
                return HashBiMap.create(mapTypeAdapter.read(in));
            }
        };
    }
}

This is my attempted TypeAdapterFactory for Guava's BiMap class. I am essentially delegating to Gson's MapTypeAdapterFactory. However, with this, a type like BiMap<UUID, String> has its keys deserialized as a String. I know this since I get a ClassCastException whenever I try to access a value with a UUID. I have also added my own UUID TypeAdapter but it still persists.

public class BiMapTypeAdapterFactory implements TypeAdapterFactory {
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
        Type type = typeToken.getType();
        if (typeToken.getRawType() != BiMap.class
                || !(type instanceof ParameterizedType)) {
            return null;
        }

        TypeToken<?> mapType = TypeToken.getParameterized(
                Map.class, ((ParameterizedType) type).getActualTypeArguments());
        TypeAdapter mapTypeAdapter = gson.getAdapter(mapType);
        return (TypeAdapter<T>) newBiMapAdapter(mapTypeAdapter);
    }

    private <K, V> TypeAdapter<BiMap<K, V>> newBiMapAdapter(TypeAdapter<Map<K, V>> mapTypeAdapter) {
        return new TypeAdapter<BiMap<K, V>>() {
            public void write(JsonWriter out, BiMap<K, V> value) throws IOException {
                mapTypeAdapter.write(out, value);
            }

            public BiMap<K, V> read(JsonReader in) throws IOException {
                return HashBiMap.create(mapTypeAdapter.read(in));
            }
        };
    }
}

I believe I found the issue, it was this line:

TypeAdapter<Map<K, V>> mapTypeAdapter = gson.getAdapter(new TypeToken<Map<K, V>>() {});

The above is the updated code. Any comments/improvements welcome.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM