The Guava Table<R, C, V> data structure is a convenience wrapper around a Map<R, Map<C, V>>. This form can be easily serialized and deserialized. Here's the basic code I'm using for that:
public static class TableSerializer extends JsonSerializer<Table<?, ?, ?>> {
@Override
public void serialize(final Table<?, ?, ?> value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeObject(value.rowMap());
}
@Override
public Class<Table<?, ?, ?>> handledType() {
return (Class)Table.class;
}
} // end class TableSerializer
public static class TableDeserializer extends JsonDeserializer<Table<?, ?, ?>> {
@Override
public Table<?, ?, ?> deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException {
final ImmutableTable.Builder<Object, Object, Object> tableBuilder = ImmutableTable.builder();
final Map<Object, Map<Object, Object>> rowMap = jp.readValueAs(Map.class);
for (final Map.Entry<Object, Map<Object, Object>> rowEntry : rowMap.entrySet()) {
final Object rowKey = rowEntry.getKey();
for (final Map.Entry<Object, Object> cellEntry : rowEntry.getValue().entrySet()) {
final Object colKey = cellEntry.getKey();
final Object val = cellEntry.getValue();
tableBuilder.put(rowKey, colKey, val);
}
}
return tableBuilder.build();
}
} // end class TableDeserializer
I have not tested if this correctly supports contextual keys or type (de)serialization. I looked at MultimapSerializer and MultimapDeserializer, and they are much more complicated even though a Multimap<K, V> is just a convenience wrapper around Map<K, Collection<V>>, so maybe this is too simplistic?
Notably, this implementation always deserializes to an ImmutableTable. Heuristics could be used to determine what Table implementation to reconstruct, e.g., if every row, column value is non-null, could create ArrayTable. HashBasedTable would be a good mutable default.
The Guava
Table<R, C, V>data structure is a convenience wrapper around aMap<R, Map<C, V>>. This form can be easily serialized and deserialized. Here's the basic code I'm using for that:I have not tested if this correctly supports contextual keys or type (de)serialization. I looked at
MultimapSerializerandMultimapDeserializer, and they are much more complicated even though aMultimap<K, V>is just a convenience wrapper aroundMap<K, Collection<V>>, so maybe this is too simplistic?Notably, this implementation always deserializes to an
ImmutableTable. Heuristics could be used to determine whatTableimplementation to reconstruct, e.g., if every row, column value is non-null, could createArrayTable.HashBasedTablewould be a good mutable default.