BiMap десериализуется как BiMap с помощью Gson

#java #gson #uuid

#java #gson #uuid

Вопрос:

 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));
            }
        };
    }
}
  

Это моя попытка TypeAdapterFactory для класса BiMap от Guava. По сути, я делегирую Gson MapTypeAdapterFactory. Однако при этом тип, подобный BiMap<UUID, String>, десериализует свои ключи в виде строки. Я знаю это, так как я получаю ClassCastException всякий раз, когда я пытаюсь получить доступ к значению с помощью UUID. Я также добавил свой собственный UUID TypeAdapter, но он все еще сохраняется.

Ответ №1:

 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));
            }
        };
    }
}
  

Я полагаю, что нашел проблему, это была эта строка:

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

Приведенный выше обновленный код. Любые комментарии / улучшения приветствуются.