我正在使用Universal Java Matrix Package它工作得非常好,但我无法让它与 Gson 很好地配合 - 序列化似乎工作得很好,但当然这是更容易的部分。
反序列化会产生一些问题,因为我试图将 JSON 反序列化为一个类的实例,该类具有 DefaultDenseGenericMatrix2D 类型的通用私有(private)成员,其中 Square 是我自己的类。 DefaultDenseGenericMatrix2D其中,实现 Matrix我用来引用实际成员的接口(interface)。因此,接口(interface)本身不是通用的,但实际上实现它的类是通用的。
我尝试过使用 RuntimeTypeAdapterFactory它不包含在 Gson 库本身中,但可以在其 GitHub 存储库中找到。
如果重要的话,我正在 Android 上使用它。
这是目前的样子:
// Grid
public class Grid implements Cloneable {
private GridPosition _position; // works fine
private GridSize _size; // this one also
private int _dimensions; // like this one, as well
private Matrix _squaresMatrix; // this little rascal refuses to play nice
public Grid(GridPosition position, GridSize size) {
_position = position;
_size = size;
Integer sizeValue = Converters.valueOf(size);
_dimensions = sizeValue != null ? sizeValue : 0;
// as you can see, it really is generic but the interface isn't
_squaresMatrix = new DefaultDenseGenericMatrix2D<Square>(_dimensions, _dimensions); // can be either 10, 15 or 20 (100, 225 or 400 elements in total)
// initializing the matrix, doesn't really matter
for (long[] coordinates : _squaresMatrix.allCoordinates()) {
Long x = coordinates[0];
Long y = coordinates[1];
_squaresMatrix.setAsObject(new Square(SquareState.VACANT, new Coordinates(x.intValue(), y.intValue())), coordinates);
}
}
// ... (unimportant stuff)
}
/*********************************************/
// Square
public class Square {
// all members are otherwise serialized correctly, on their own
private SquareState _state;
private Coordinates _coordinates;
private Ship _owner;
public Square(SquareState state, Coordinates coordinates) {
_state = state;
_coordinates = coordinates;
_owner = null;
}
// ... (unimportant stuff)
}
/*********************************************/
// constructing the Gson object
Type genericType = new TypeToken<DefaultDenseGenericMatrix2D<Square>>(){}.getType(); // not used (where to put it?)
final RuntimeTypeAdapterFactory<Matrix> typeFactory = RuntimeTypeAdapterFactory
.of(Matrix.class, "_squaresMatrix")
// DefaultDenseGenericMatrix2D<Square>.class is illegal, of course (wouldn't make sense either way due to the infamous type erasure)
.registerSubtype(DefaultDenseGenericMatrix2D.class);
GsonBuilder builder = new GsonBuilder().registerTypeAdapterFactory(typeFactory);
Gson gson = builder.create();
在反序列化期间,“_squaresMatrix”字段确实被反序列化,但我得到的不是 Square 类型的 DefaultDenseGenericMatrix2D,而是 LinkedTreeMap 类型,因为 Gson 不知道实际使用哪种类型,并且 DefaultDenseGenericMatrix2D 类本身可以很好地处理普通旧对象,当然。
我相信解决方案可能是在某个地方使用 TypeToken 类,但我只是不知道在哪里合并它。
作为最后的手段,我可以将 LinkedTreeMap 实例映射到 Square 类型的实例,因为数据就在那里,但如果可能的话,我想尽量避免这种情况。
提前谢谢您。
最佳答案
使用 InstanceCreator
允许您告诉 Gson 如何创建特定类型的实例。
在这里你可以告诉它创建一个 DefaultDenseGenericMatrix2D<Square>
每次它找到 Matrix
:
GsonBuilder builder = new GsonBuilder().registerTypeAdapter(Matrix.class, new MatrixInstanceCreator());
Gson gson = builder.create();
与 MatrixInstanceCreator
是:
public class MatrixInstanceCreator() implements InstanceCreator<Matrix> {
@Override
public Matrix createInstance() {
// the dimensions will be overridden by Gson anyway
return new DefaultDenseGenericMatrix2D<Square>(0, 0);
}
}
警告:尽管如此,这并不是很强大,因为每个Matrix
在您的应用程序中将创建为 DefaultDenseGenericMatrix2D<Square>
。但是,如果您只有这个,或者您的所有Matrix
属于具体类型,无论如何这都会满足您的需求。
关于java - 使用 Gson 反序列化可通过接口(interface)引用访问的通用类实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39556500/