【问题标题】:How to use Gson with guava tables如何将 Gson 与番石榴表一起使用
【发布时间】:2021-06-26 06:42:04
【问题描述】:

我将我的数据存储在 Guava Table 中,并需要将其保存到 JSON 文件

我设法让 Gson#toJson 方法正常工作,但我在将其读回表格时遇到了困难。

有人知道我能做什么吗?

【问题讨论】:

    标签: java gson guava


    【解决方案1】:

    您应该编写自己的一组Serializer/Deserializers 甚至TypeAdapter(Factory)。这是一个基于https://github.com/acebaggins/guava-gson-serializers的示例实现:

    static class TableSerializer implements JsonSerializer<Table> {
    
        @Override
        public JsonElement serialize(Table table, Type type, JsonSerializationContext context) {
            return context.serialize(table.rowMap());
        }
    }
    
    static class TableDeserializer implements JsonDeserializer<Table<?, ?, ?>> {
    
        @Override
        public Table deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
            Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments();
            Type parameterizedType = hashMapOf(
                    typeArguments[0],
                    hashMapOf(typeArguments[1], typeArguments[2]).getType()).getType();
            Map<?, Map<?, ?>> map = context.deserialize(json, parameterizedType);
    
            Table<Object, Object, Object> table = HashBasedTable.create();
            for (Object rowKey : map.keySet()) {
                Map<?, ?> rowMap = map.get(rowKey);
                for (Object columnKey : rowMap.keySet()) {
                    Object value = rowMap.get(columnKey);
                    table.put(rowKey, columnKey, value);
                }
            }
            return table;
        }
    }
    
    // see https://github.com/acebaggins/guava-gson-serializers/blob/master/src/main/java/com/baggonius/gson/immutable/Types.java
    static <K, V> TypeToken<HashMap<K, V>> hashMapOf(Type key, Type value) {
        TypeParameter<K> newKeyTypeParameter = new TypeParameter<K>() {};
        TypeParameter<V> newValueTypeParameter = new TypeParameter<V>() {};
        return new TypeToken<HashMap<K, V>>() {}
                .where(newKeyTypeParameter, typeTokenOf(key))
                .where(newValueTypeParameter, typeTokenOf(value));
    }
    
    private static <E> TypeToken<E> typeTokenOf(Type type) {
        return (TypeToken<E>) TypeToken.of(type);
    }
    

    应该这样使用:

    @Test
    public void shouldSerializeAndDeserializeGuavaTable() {
        Table<Integer, Integer, String> table = ImmutableTable.<Integer, Integer, String>builder()
                .put(1, 1, "eleven")
                .put(1, 0, "ten")
                .put(4, 2, "forty-two")
                .build();
    
        Gson gson = new GsonBuilder()
                .registerTypeHierarchyAdapter(Table.class, new TableSerializer())
                .registerTypeHierarchyAdapter(Table.class, new TableDeserializer())
                .create();
        String tableAsString = gson.toJson(table); // {"1":{"1":"eleven","0":"ten"},"4":{"2":"forty-two"}}
    
        Table<Integer, Integer, String> deserializedTable = gson.fromJson( // {1={0=ten, 1=eleven}, 4={2=forty-two}}
                tableAsString,
                new TypeToken<Table<Integer, Integer, String>>() {}.getType());
    
        Assertions.assertThat(deserializedTable)
                .hasSize(3)
                .containsCell(1, 1, "eleven")
                .containsCell(1, 0, "ten")
                .containsCell(4, 2, "forty-two");
    }
    

    如果我找到一些空闲时间,我可能会创建一个 PR 到 https://github.com/acebaggins/guava-gson-serializers,并对表(反)序列化进行适当测试的更改。

    【讨论】:

    • 谢谢!感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-04
    相关资源
    最近更新 更多