【发布时间】:2016-03-21 15:09:34
【问题描述】:
我正在寻找一种使用 GSON 将 MongoDB 文档读入 POJO 的方法。它工作得很好,直到你遇到像日期和长这样的东西。
我想为 Gson 编写一个自定义适配器,它将转换任何 BSON 编码长。阅读this 帖子我已经创建了自己的适配器:
public class BsonLongTypeAdapter extends TypeAdapter<Long>
{
@Override
public void write(JsonWriter out, Long value) throws IOException
{
out.beginObject()
.name("$numberLong")
.value(value.toString())
.endObject();
}
@Override
public Long read(JsonReader in) throws IOException
{
in.beginObject();
assert "$numberLong".equals(in.nextName());
Long value = in.nextLong();
in.endObject();
return value;
}
}
我已经定义了以下测试来检查这是否有效:
@Test
public void canWriteCorrectJSON() {
Gson gson = new GsonBuilder().registerTypeAdapter(Long.class, new BsonLongTypeAdapter()).create();
MyTestObject obj = new MyTestObject(1458569479431L);
String gsonString = gson.toJson(obj);
assertEquals("{\"timestamp\":{\"$numberLong\":\"1458569479431\"}}",gsonString);
}
@Test
public void canReadFromJSON() {
Gson gson = new GsonBuilder().registerTypeAdapter(Long.class, new BsonLongTypeAdapter()).create();
MyTestObject actualTaskObject = gson.fromJson("{\"timestamp\":{\"$numberLong\":\"1458569479431\"}}", MyTestObject.class);
MyTestObject taskObject = new MyTestObject(1458569479431L);
assertEquals(taskObject.getTimestamp(),actualTaskObject.getTimestamp());
}
private static class MyTestObject
{
long timestamp;
public MyTestObject(long ts)
{
timestamp = ts;
}
public long getTimestamp()
{
return timestamp;
}
public void setTimestamp(long timestamp)
{
this.timestamp = timestamp;
}
}
第一个(写入)测试工作正常,但读取测试失败:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a long but was BEGIN_OBJECT at line 1 column 15 path $.timestamp
因为我的适配器的读取函数永远不会被调用。我想这可能是因为我想映射到 MyTestObject 而不是 Long,但我不想为所有包含 long 的类编写适配器。
是否可以为 GSON 编写一个适配器,将我发送的所有 BSON long 转换为它?
【问题讨论】: