如何将 Gson 与番石榴表一起使用
How to use Gson with guava tables
我将我的数据存储在 Guava Table
中,需要将其保存到 JSON 文件.
我设法使 Gson#toJson
方法正常工作,但我很难将其读回 table。
有人知道我能做什么吗?
你应该自己写一套Serializer
/Deserializer
s or even TypeAdapter(Factory)
. Here's a sample implementation based on 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,其中包含针对 Table(反)序列化的经过适当测试的更改。
我将我的数据存储在 Guava Table
中,需要将其保存到 JSON 文件.
我设法使 Gson#toJson
方法正常工作,但我很难将其读回 table。
有人知道我能做什么吗?
你应该自己写一套Serializer
/Deserializer
s or even TypeAdapter(Factory)
. Here's a sample implementation based on 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,其中包含针对 Table(反)序列化的经过适当测试的更改。