Конвертировать Guava HashMultimap к json


Я хочу напечатать HashMultiMap как json.

HashMultimap<String,Object> multimap = HashMultimap.create();
multimap.put("a",Obj1);
multimap.put("a",Obj3);
multimap.put("b",Obj2);

К

{ 
  "a":[Obj1,Obj3],
  "b":[Obj2]
}

Obj1 и другие объекты снова должны быть в json(чтобы сохранить его чистым, я показал его как объекты)
Я могу перебирать отдельные ключи и преобразовывать набор объектов в json, используя библиотеки, такие как Gson.

, но чтобы сделать весь снимок HashMultimap, я хочу, чтобы преобразовать его в формат JSON и осмотрите его.

Gson не может преобразовать всю карту, но может сделать отдельные значения (список объектов в json)

2 11

2 ответа:

Вызов asMap() сначала на Мультикарточке. Это преобразует MultiMap в стандартную карту, где каждое значение является коллекцией.

В вашем примере тип результирующей карты - Map<String, Collection<Object>>. Gson должен быть в состоянии сериализовать это правильно.

Вам нужно написать JsonAdapter или оба JsonDeserializer и JsonSerializer. Это довольно ужасно, но я хотела попробовать.

В принципе, вы делегируете все Map<String, Collection<V>>.

static class MultimapAdapter implements JsonDeserializer<Multimap<String, ?>>, JsonSerializer<Multimap<String, ?>> {
    @Override public Multimap<String, ?> deserialize(JsonElement json, Type type,
            JsonDeserializationContext context) throws JsonParseException {
        final HashMultimap<String, Object> result = HashMultimap.create();
        final Map<String, Collection<?>> map = context.deserialize(json, multimapTypeToMapType(type));
        for (final Map.Entry<String, ?> e : map.entrySet()) {
            final Collection<?> value = (Collection<?>) e.getValue();
            result.putAll(e.getKey(), value);
        }
        return result;
    }

    @Override public JsonElement serialize(Multimap<String, ?> src, Type type, JsonSerializationContext context) {
        final Map<?, ?> map = src.asMap();
        return context.serialize(map);
    }

    private <V> Type multimapTypeToMapType(Type type) {
        final Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments();
        assert typeArguments.length == 2;
        @SuppressWarnings("unchecked")
        final TypeToken<Map<String, Collection<V>>> mapTypeToken = new TypeToken<Map<String, Collection<V>>>() {}
        .where(new TypeParameter<V>() {}, (TypeToken<V>) TypeToken.of(typeArguments[1]));
        return mapTypeToken.getType();
    }
}

Полный код, включая тест может быть найден здесь.